@jixo/cli 0.3.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/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +74 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/doctor/config.d.ts +3 -0
- package/dist/commands/doctor/config.d.ts.map +1 -0
- package/dist/commands/doctor/config.js +30 -0
- package/dist/commands/doctor/config.js.map +1 -0
- package/dist/commands/doctor/doctor.d.ts +18 -0
- package/dist/commands/doctor/doctor.d.ts.map +1 -0
- package/dist/commands/doctor/doctor.js +125 -0
- package/dist/commands/doctor/doctor.js.map +1 -0
- package/dist/commands/doctor/doctor.test.d.ts +2 -0
- package/dist/commands/doctor/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor/doctor.test.js +14 -0
- package/dist/commands/doctor/doctor.test.js.map +1 -0
- package/dist/commands/doctor/index.d.ts +2 -0
- package/dist/commands/doctor/index.d.ts.map +1 -0
- package/dist/commands/doctor/index.js +19 -0
- package/dist/commands/doctor/index.js.map +1 -0
- package/dist/commands/doctor/types.d.ts +30 -0
- package/dist/commands/doctor/types.d.ts.map +1 -0
- package/dist/commands/doctor/types.js +3 -0
- package/dist/commands/doctor/types.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +57 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/prompts/list.d.ts +2 -0
- package/dist/commands/prompts/list.d.ts.map +1 -0
- package/dist/commands/prompts/list.js +14 -0
- package/dist/commands/prompts/list.js.map +1 -0
- package/dist/commands/prompts/upgrade.d.ts +4 -0
- package/dist/commands/prompts/upgrade.d.ts.map +1 -0
- package/dist/commands/prompts/upgrade.js +17 -0
- package/dist/commands/prompts/upgrade.js.map +1 -0
- package/dist/commands/run.d.ts +5 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +36 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/tasks/ai-tools.d.ts +268 -0
- package/dist/commands/tasks/ai-tools.d.ts.map +1 -0
- package/dist/commands/tasks/ai-tools.js +64 -0
- package/dist/commands/tasks/ai-tools.js.map +1 -0
- package/dist/commands/tasks/model-providers.d.ts +9 -0
- package/dist/commands/tasks/model-providers.d.ts.map +1 -0
- package/dist/commands/tasks/model-providers.js +53 -0
- package/dist/commands/tasks/model-providers.js.map +1 -0
- package/dist/commands/tasks/run-ai-task.d.ts +4 -0
- package/dist/commands/tasks/run-ai-task.d.ts.map +1 -0
- package/dist/commands/tasks/run-ai-task.js +246 -0
- package/dist/commands/tasks/run-ai-task.js.map +1 -0
- package/dist/commands/tasks/run-ai.d.ts +278 -0
- package/dist/commands/tasks/run-ai.d.ts.map +1 -0
- package/dist/commands/tasks/run-ai.js +179 -0
- package/dist/commands/tasks/run-ai.js.map +1 -0
- package/dist/commands/tasks/run.d.ts +5 -0
- package/dist/commands/tasks/run.d.ts.map +1 -0
- package/dist/commands/tasks/run.js +46 -0
- package/dist/commands/tasks/run.js.map +1 -0
- package/dist/commands/upgrade.d.ts +4 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +17 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/config.d.ts +206 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/env.d.ts +17 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +26 -0
- package/dist/env.js.map +1 -0
- package/dist/helper/find-changes.d.ts +3 -0
- package/dist/helper/find-changes.d.ts.map +1 -0
- package/dist/helper/find-changes.js +106 -0
- package/dist/helper/find-changes.js.map +1 -0
- package/dist/helper/find-changes.test.d.ts +2 -0
- package/dist/helper/find-changes.test.d.ts.map +1 -0
- package/dist/helper/find-changes.test.js +22 -0
- package/dist/helper/find-changes.test.js.map +1 -0
- package/dist/helper/prompts-loader.d.ts +5 -0
- package/dist/helper/prompts-loader.d.ts.map +1 -0
- package/dist/helper/prompts-loader.js +28 -0
- package/dist/helper/prompts-loader.js.map +1 -0
- package/dist/helper/prompts.d.ts +3 -0
- package/dist/helper/prompts.d.ts.map +1 -0
- package/dist/helper/prompts.js +28 -0
- package/dist/helper/prompts.js.map +1 -0
- package/dist/helper/resolve-ai-tasks.d.ts +25 -0
- package/dist/helper/resolve-ai-tasks.d.ts.map +1 -0
- package/dist/helper/resolve-ai-tasks.js +91 -0
- package/dist/helper/resolve-ai-tasks.js.map +1 -0
- package/dist/helper/run-ai.d.ts +12 -0
- package/dist/helper/run-ai.d.ts.map +1 -0
- package/dist/helper/run-ai.js +179 -0
- package/dist/helper/run-ai.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.json +29 -0
- package/package.json +47 -0
- package/prompts/i18n.md +108 -0
- package/prompts/readme-writer.md +120 -0
- package/prompts/user.md +88 -0
- package/prompts/writer.md +13 -0
- package/scripts/gen-prompts.ts +27 -0
- package/src/cli.ts +96 -0
- package/src/commands/doctor/config.ts +30 -0
- package/src/commands/doctor/doctor.test.ts +17 -0
- package/src/commands/doctor/doctor.ts +151 -0
- package/src/commands/doctor/index.ts +21 -0
- package/src/commands/doctor/types.ts +39 -0
- package/src/commands/init.ts +64 -0
- package/src/commands/prompts/list.ts +14 -0
- package/src/commands/prompts/upgrade.ts +16 -0
- package/src/commands/tasks/ai-tools.ts +65 -0
- package/src/commands/tasks/model-providers.ts +54 -0
- package/src/commands/tasks/run-ai-task.ts +263 -0
- package/src/commands/tasks/run.ts +52 -0
- package/src/config.ts +39 -0
- package/src/env.ts +32 -0
- package/src/helper/find-changes.test.ts +23 -0
- package/src/helper/find-changes.ts +109 -0
- package/src/helper/prompts-loader.ts +33 -0
- package/src/helper/resolve-ai-tasks.ts +126 -0
- package/src/index.ts +8 -0
- package/src/prompts.json +29 -0
- package/tsconfig.json +15 -0
- package/tsconfig.tsbuildinfo +1 -0
package/dist/cli.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,MAAM,GAAU,OAAM,MAAM,EAAiB,kBAsFzD,CAAC"}
|
package/dist/cli.js
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
import { cwdResolver } from "@gaubee/node";
|
2
|
+
import yargs from "yargs";
|
3
|
+
import { hideBin } from "yargs/helpers";
|
4
|
+
import { doctor } from "./commands/doctor/index.js";
|
5
|
+
import { init } from "./commands/init.js";
|
6
|
+
import { listPrompts } from "./commands/prompts/list.js";
|
7
|
+
import { upgradePrompts } from "./commands/prompts/upgrade.js";
|
8
|
+
import { run } from "./commands/tasks/run.js";
|
9
|
+
export const runCli = async (args = process.argv) => {
|
10
|
+
const cli = await yargs(hideBin(args))
|
11
|
+
.command("doctor", "Check the requirements for run jixo", (yargs) => yargs, () => {
|
12
|
+
doctor();
|
13
|
+
})
|
14
|
+
.command("init [dir]", "Create a new JIXO project", (yargs) => {
|
15
|
+
return yargs.positional("dir", {
|
16
|
+
describe: "The directory to create the JIXO config",
|
17
|
+
default: "./",
|
18
|
+
});
|
19
|
+
}, (argv) => {
|
20
|
+
init(cwdResolver(argv.dir));
|
21
|
+
})
|
22
|
+
.command("run [filter...]", "Run JIXO tasks", (yargs) => {
|
23
|
+
return yargs
|
24
|
+
.positional("filter", {
|
25
|
+
describe: 'Fliter tasks by name or directory(starts with "./")',
|
26
|
+
array: true,
|
27
|
+
default: [],
|
28
|
+
})
|
29
|
+
.option("dir", {
|
30
|
+
alias: "D",
|
31
|
+
type: "string",
|
32
|
+
description: "The project directory with JIXO config",
|
33
|
+
});
|
34
|
+
}, (argv) => {
|
35
|
+
const filters = argv.filter.map((v) => v.toString().split(/[\s,]+/)).flat();
|
36
|
+
const nameFilter = filters.filter((f) => !f.startsWith("./"));
|
37
|
+
const dirFilter = filters.filter((f) => f.startsWith("./"));
|
38
|
+
run(cwdResolver(argv.dir ?? ""), { nameFilter, dirFilter });
|
39
|
+
})
|
40
|
+
.command("prompts", "Manage prompts", (yargs) => {
|
41
|
+
return (yargs
|
42
|
+
//
|
43
|
+
.option("dir", {
|
44
|
+
alias: "D",
|
45
|
+
type: "string",
|
46
|
+
description: "The project directory with JIXO config",
|
47
|
+
})
|
48
|
+
.option("mirrorUrl", {
|
49
|
+
alias: "M",
|
50
|
+
type: "string",
|
51
|
+
description: "The Url for download prompts",
|
52
|
+
})
|
53
|
+
.option("upgrade", {
|
54
|
+
alias: "U",
|
55
|
+
type: "boolean",
|
56
|
+
description: "Upgrade builtin prompts",
|
57
|
+
}));
|
58
|
+
}, async (argv) => {
|
59
|
+
if (argv.upgrade) {
|
60
|
+
upgradePrompts(argv.dir ? cwdResolver(argv.dir) : cwdResolver(), { mirrorUrl: argv.mirrorUrl });
|
61
|
+
}
|
62
|
+
else {
|
63
|
+
listPrompts();
|
64
|
+
}
|
65
|
+
})
|
66
|
+
.strict();
|
67
|
+
const argv = await cli.parse();
|
68
|
+
if (argv._.length === 0) {
|
69
|
+
cli.showHelp();
|
70
|
+
console.log("⎯".repeat(Math.max(4, process.stdout.columns)));
|
71
|
+
await doctor();
|
72
|
+
}
|
73
|
+
};
|
74
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import {cwdResolver} from \"@gaubee/node\";\nimport yargs from \"yargs\";\nimport {hideBin} from \"yargs/helpers\";\nimport {doctor} from \"./commands/doctor/index.js\";\nimport {init} from \"./commands/init.js\";\nimport {listPrompts} from \"./commands/prompts/list.js\";\nimport {upgradePrompts} from \"./commands/prompts/upgrade.js\";\nimport {run} from \"./commands/tasks/run.js\";\n\nexport const runCli = async (args: string[] = process.argv) => {\n const cli = await yargs(hideBin(args))\n .command(\n \"doctor\",\n \"Check the requirements for run jixo\",\n (yargs) => yargs,\n () => {\n doctor();\n },\n )\n .command(\n \"init [dir]\",\n \"Create a new JIXO project\",\n (yargs) => {\n return yargs.positional(\"dir\", {\n describe: \"The directory to create the JIXO config\",\n default: \"./\",\n });\n },\n (argv) => {\n init(cwdResolver(argv.dir));\n },\n )\n .command(\n \"run [filter...]\",\n \"Run JIXO tasks\",\n (yargs) => {\n return yargs\n .positional(\"filter\", {\n describe: 'Fliter tasks by name or directory(starts with \"./\")',\n array: true,\n default: [],\n })\n .option(\"dir\", {\n alias: \"D\",\n type: \"string\",\n description: \"The project directory with JIXO config\",\n });\n },\n (argv) => {\n const filters = argv.filter.map((v) => v.toString().split(/[\\s,]+/)).flat();\n const nameFilter = filters.filter((f) => !f.startsWith(\"./\"));\n const dirFilter = filters.filter((f) => f.startsWith(\"./\"));\n run(cwdResolver(argv.dir ?? \"\"), {nameFilter, dirFilter});\n },\n )\n .command(\n \"prompts\",\n \"Manage prompts\",\n (yargs) => {\n return (\n yargs\n //\n .option(\"dir\", {\n alias: \"D\",\n type: \"string\",\n description: \"The project directory with JIXO config\",\n })\n .option(\"mirrorUrl\", {\n alias: \"M\",\n type: \"string\",\n description: \"The Url for download prompts\",\n })\n .option(\"upgrade\", {\n alias: \"U\",\n type: \"boolean\",\n description: \"Upgrade builtin prompts\",\n })\n );\n },\n async (argv) => {\n if (argv.upgrade) {\n upgradePrompts(argv.dir ? cwdResolver(argv.dir) : cwdResolver(), {mirrorUrl: argv.mirrorUrl});\n } else {\n listPrompts();\n }\n },\n )\n .strict();\n const argv = await cli.parse();\n\n if (argv._.length === 0) {\n cli.showHelp();\n console.log(\"⎯\".repeat(Math.max(4, process.stdout.columns)));\n await doctor();\n }\n};\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AAC7C,eAAO,MAAM,cAAc,EAAE,YA2B5B,CAAC"}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { blue, green } from "@gaubee/nodekit";
|
2
|
+
export const myDoctorConfig = [
|
3
|
+
{
|
4
|
+
id: "pnpm",
|
5
|
+
displayName: "PNPM Package Manager",
|
6
|
+
versionCommand: "pnpm --version",
|
7
|
+
versionParseRegex: /(\d+\.\d+\.\d+)/, // Assumes pnpm --version outputs just the version or "X.Y.Z ..."
|
8
|
+
minVersion: "10.9.0",
|
9
|
+
installationHint: `Install pnpm via npm: ${green("npm install -g pnpm")}. Or visit ${blue("https://pnpm.io/installation")}`,
|
10
|
+
},
|
11
|
+
{
|
12
|
+
id: "uv",
|
13
|
+
displayName: "UVX CLI",
|
14
|
+
versionCommand: "uvx --version",
|
15
|
+
// Let's assume uvx outputs something like "uvx version 0.7.8"
|
16
|
+
versionParseRegex: /uvx\s+(\d+\.\d+\.\d+)/,
|
17
|
+
minVersion: "0.7.0",
|
18
|
+
installationHint: `Install uv via pip: ${green("pip install uv")}. Or visit ${blue("https://docs.astral.sh/uv/getting-started/installation")}`,
|
19
|
+
},
|
20
|
+
{
|
21
|
+
id: "node",
|
22
|
+
displayName: "Node.js Runtime",
|
23
|
+
versionCommand: "node --version",
|
24
|
+
versionParseRegex: /v([\d.]+)/, // node --version outputs "v18.17.0"
|
25
|
+
minVersion: "18.0.0",
|
26
|
+
installationHint: "Install Node.js from https://nodejs.org/",
|
27
|
+
optional: true, // Example of an optional check
|
28
|
+
},
|
29
|
+
];
|
30
|
+
//# sourceMappingURL=config.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/commands/doctor/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAE5C,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C;QACE,EAAE,EAAE,MAAM;QACV,WAAW,EAAE,sBAAsB;QACnC,cAAc,EAAE,gBAAgB;QAChC,iBAAiB,EAAE,iBAAiB,EAAE,iEAAiE;QACvG,UAAU,EAAE,QAAQ;QACpB,gBAAgB,EAAE,yBAAyB,KAAK,CAAC,qBAAqB,CAAC,cAAc,IAAI,CAAC,8BAA8B,CAAC,EAAE;KAC5H;IACD;QACE,EAAE,EAAE,IAAI;QACR,WAAW,EAAE,SAAS;QACtB,cAAc,EAAE,eAAe;QAC/B,8DAA8D;QAC9D,iBAAiB,EAAE,uBAAuB;QAC1C,UAAU,EAAE,OAAO;QACnB,gBAAgB,EAAE,uBAAuB,KAAK,CAAC,gBAAgB,CAAC,cAAc,IAAI,CAAC,wDAAwD,CAAC,EAAE;KAC/I;IACD;QACE,EAAE,EAAE,MAAM;QACV,WAAW,EAAE,iBAAiB;QAC9B,cAAc,EAAE,gBAAgB;QAChC,iBAAiB,EAAE,WAAW,EAAE,oCAAoC;QACpE,UAAU,EAAE,QAAQ;QACpB,gBAAgB,EAAE,0CAA0C;QAC5D,QAAQ,EAAE,IAAI,EAAE,+BAA+B;KAChD;CACF,CAAC","sourcesContent":["import {blue, green} from \"@gaubee/nodekit\";\nimport type {DoctorConfig} from \"./types.js\";\nexport const myDoctorConfig: DoctorConfig = [\n {\n id: \"pnpm\",\n displayName: \"PNPM Package Manager\",\n versionCommand: \"pnpm --version\",\n versionParseRegex: /(\\d+\\.\\d+\\.\\d+)/, // Assumes pnpm --version outputs just the version or \"X.Y.Z ...\"\n minVersion: \"10.9.0\", \n installationHint: `Install pnpm via npm: ${green(\"npm install -g pnpm\")}. Or visit ${blue(\"https://pnpm.io/installation\")}`,\n },\n {\n id: \"uv\",\n displayName: \"UVX CLI\",\n versionCommand: \"uvx --version\",\n // Let's assume uvx outputs something like \"uvx version 0.7.8\"\n versionParseRegex: /uvx\\s+(\\d+\\.\\d+\\.\\d+)/,\n minVersion: \"0.7.0\",\n installationHint: `Install uv via pip: ${green(\"pip install uv\")}. Or visit ${blue(\"https://docs.astral.sh/uv/getting-started/installation\")}`,\n },\n {\n id: \"node\",\n displayName: \"Node.js Runtime\",\n versionCommand: \"node --version\",\n versionParseRegex: /v([\\d.]+)/, // node --version outputs \"v18.17.0\"\n minVersion: \"18.0.0\",\n installationHint: \"Install Node.js from https://nodejs.org/\",\n optional: true, // Example of an optional check\n },\n];\n"]}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import type { DoctorConfig } from "./types.js";
|
2
|
+
export interface ToolCheckResult {
|
3
|
+
id: string;
|
4
|
+
displayName: string;
|
5
|
+
exists: boolean;
|
6
|
+
version?: string;
|
7
|
+
requiredVersion?: string;
|
8
|
+
meetsVersionRequirement: boolean;
|
9
|
+
isOptional: boolean;
|
10
|
+
message: string;
|
11
|
+
installationHint?: string;
|
12
|
+
}
|
13
|
+
export interface DoctorReport {
|
14
|
+
overallSuccess: boolean;
|
15
|
+
results: ToolCheckResult[];
|
16
|
+
}
|
17
|
+
export declare function runDoctor(config: DoctorConfig, enableLog?: boolean): Promise<DoctorReport>;
|
18
|
+
//# sourceMappingURL=doctor.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/doctor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AAM7C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,OAAO,CAAC;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAaD,wBAAsB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,GAAE,OAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CA8GtG"}
|
@@ -0,0 +1,125 @@
|
|
1
|
+
// doctor.ts
|
2
|
+
import { blue, cyan, green, red, spinner, yellow } from "@gaubee/nodekit";
|
3
|
+
import { execSync } from "child_process";
|
4
|
+
import semver from "semver";
|
5
|
+
import { iter_map_not_null } from "@gaubee/util";
|
6
|
+
const CHECK_MARK = green("✔");
|
7
|
+
const CROSS_MARK = red("✖");
|
8
|
+
const WARN_MARK = yellow("⚠");
|
9
|
+
async function executeCommand(command) {
|
10
|
+
return new Promise((resolve) => {
|
11
|
+
try {
|
12
|
+
const stdout = execSync(command, { encoding: "utf8", stdio: "pipe" });
|
13
|
+
resolve({ stdout, stderr: "" });
|
14
|
+
}
|
15
|
+
catch (e) {
|
16
|
+
resolve({ stdout: "", stderr: e.stderr || "", error: e });
|
17
|
+
}
|
18
|
+
});
|
19
|
+
}
|
20
|
+
export async function runDoctor(config, enableLog = true) {
|
21
|
+
const LOG_TITLE = "Running Environment Doctor 🏥\n\n";
|
22
|
+
const logger = spinner(LOG_TITLE);
|
23
|
+
if (enableLog) {
|
24
|
+
logger.start();
|
25
|
+
}
|
26
|
+
const results = [];
|
27
|
+
let overallSuccess = true;
|
28
|
+
let overallWarn = false;
|
29
|
+
const tool_logs = [];
|
30
|
+
for (const [index, tool] of config.entries()) {
|
31
|
+
const TOOL_LOG_TITLE = `${blue(`[${tool.id}]`)} ${cyan(tool.displayName)}`;
|
32
|
+
const SUCCESS_MARK = () => CHECK_MARK;
|
33
|
+
const FAIL_MARK = () => {
|
34
|
+
overallWarn = true;
|
35
|
+
return tool.optional ? WARN_MARK : CROSS_MARK;
|
36
|
+
};
|
37
|
+
const setToolLog = (update) => {
|
38
|
+
const log = update(tool_logs[index] ?? "");
|
39
|
+
tool_logs[index] = (Array.isArray(log) ? iter_map_not_null(log, (v) => (v ? v : null)) : [log]).map((line) => " " + line).join("\n");
|
40
|
+
logger.text = LOG_TITLE + tool_logs.join("\n");
|
41
|
+
};
|
42
|
+
setToolLog(() => `Checking ${TOOL_LOG_TITLE}... `);
|
43
|
+
let tool_log = [];
|
44
|
+
const result = {
|
45
|
+
id: tool.id,
|
46
|
+
displayName: tool.displayName,
|
47
|
+
exists: false,
|
48
|
+
meetsVersionRequirement: false, // Assume failure until proven otherwise
|
49
|
+
isOptional: !!tool.optional,
|
50
|
+
message: "",
|
51
|
+
requiredVersion: tool.minVersion,
|
52
|
+
installationHint: tool.installationHint,
|
53
|
+
};
|
54
|
+
const execResult = await executeCommand(tool.versionCommand);
|
55
|
+
if (execResult.error || execResult.stderr.includes("command not found") || execResult.stderr.includes("not recognized")) {
|
56
|
+
result.exists = false;
|
57
|
+
result.message = `'${tool.id}' command not found or failed to execute.`;
|
58
|
+
tool_log = [
|
59
|
+
//
|
60
|
+
`${FAIL_MARK()} ${TOOL_LOG_TITLE}`,
|
61
|
+
` ${red(result.message)}`,
|
62
|
+
tool.installationHint && ` ${yellow("Hint:")} ${tool.installationHint}`,
|
63
|
+
];
|
64
|
+
}
|
65
|
+
else {
|
66
|
+
result.exists = true;
|
67
|
+
const output = execResult.stdout.trim();
|
68
|
+
const match = output.match(tool.versionParseRegex);
|
69
|
+
if (match && match[1]) {
|
70
|
+
result.version = semver.clean(match[1]) || undefined; // Clean the version string
|
71
|
+
if (result.version) {
|
72
|
+
if (tool.minVersion) {
|
73
|
+
if (semver.gte(result.version, tool.minVersion)) {
|
74
|
+
result.meetsVersionRequirement = true;
|
75
|
+
result.message = `Version ${result.version} satisfies >=${tool.minVersion}.`;
|
76
|
+
tool_log.push(`${SUCCESS_MARK()} ${TOOL_LOG_TITLE} (v${result.version})`);
|
77
|
+
}
|
78
|
+
else {
|
79
|
+
result.meetsVersionRequirement = false;
|
80
|
+
result.message = `Version ${result.version} is older than required >=${tool.minVersion}.`;
|
81
|
+
tool_log.push(`${FAIL_MARK()} ${TOOL_LOG_TITLE} (v${result.version} - required: >=${tool.minVersion})`);
|
82
|
+
tool_log.push(` ${red(result.message)}`);
|
83
|
+
if (tool.installationHint) {
|
84
|
+
tool_log.push(` ${yellow("Hint:")} ${tool.installationHint}`);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
else {
|
89
|
+
// No minimum version specified, just existence is enough
|
90
|
+
result.meetsVersionRequirement = true;
|
91
|
+
result.message = `Found version ${result.version}. No minimum version specified.`;
|
92
|
+
tool_log.push(`${SUCCESS_MARK()} ${TOOL_LOG_TITLE} (v${result.version} - existence check only)`);
|
93
|
+
}
|
94
|
+
}
|
95
|
+
else {
|
96
|
+
// Regex matched but couldn't clean version (should be rare with semver.clean)
|
97
|
+
result.meetsVersionRequirement = false;
|
98
|
+
result.message = `Could not parse a valid version string from output: "${output}". Regex: ${tool.versionParseRegex}`;
|
99
|
+
tool_log.push(`${FAIL_MARK()} ${TOOL_LOG_TITLE}`);
|
100
|
+
tool_log.push(` ${red(result.message)}`);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
else {
|
104
|
+
result.meetsVersionRequirement = false;
|
105
|
+
result.message = `Could not parse version from output: "${output}". Regex: ${tool.versionParseRegex}`;
|
106
|
+
tool_log.push(`${FAIL_MARK}`);
|
107
|
+
tool_log.push(` ${red(result.message)}`);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
setToolLog(() => tool_log);
|
111
|
+
results.push(result);
|
112
|
+
if (!result.meetsVersionRequirement && !result.isOptional) {
|
113
|
+
overallSuccess = false;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
const LOG_SUMMERY = `${overallSuccess ? (overallWarn ? "⚠️ " : "✅") : "💊"} JIXO Environment Doctor 🏥\n\n`;
|
117
|
+
logger.stopAndPersist({
|
118
|
+
text: LOG_SUMMERY + tool_logs.join("\n") + "\n",
|
119
|
+
});
|
120
|
+
return {
|
121
|
+
overallSuccess,
|
122
|
+
results,
|
123
|
+
};
|
124
|
+
}
|
125
|
+
//# sourceMappingURL=doctor.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/commands/doctor/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["// doctor.ts\nimport {blue, cyan, green, red, spinner, yellow} from \"@gaubee/nodekit\";\nimport {execSync} from \"child_process\";\nimport semver from \"semver\";\n\nimport {iter_map_not_null} from \"@gaubee/util\";\nimport type {DoctorConfig} from \"./types.js\"; // Assuming types.ts\n\nconst CHECK_MARK = green(\"✔\");\nconst CROSS_MARK = red(\"✖\");\nconst WARN_MARK = yellow(\"⚠\");\n\nexport interface ToolCheckResult {\n id: string;\n displayName: string;\n exists: boolean;\n version?: string; // Actual version found\n requiredVersion?: string; // From config\n meetsVersionRequirement: boolean; // True if version >= minVersion or if minVersion not set & exists\n isOptional: boolean;\n message: string;\n installationHint?: string;\n}\n\nexport interface DoctorReport {\n overallSuccess: boolean;\n results: ToolCheckResult[];\n}\n\nasync function executeCommand(command: string): Promise<{stdout: string; stderr: string; error?: Error}> {\n return new Promise((resolve) => {\n try {\n const stdout = execSync(command, {encoding: \"utf8\", stdio: \"pipe\"});\n resolve({stdout, stderr: \"\"});\n } catch (e: any) {\n resolve({stdout: \"\", stderr: e.stderr || \"\", error: e});\n }\n });\n}\n\nexport async function runDoctor(config: DoctorConfig, enableLog: boolean = true): Promise<DoctorReport> {\n const LOG_TITLE = \"Running Environment Doctor 🏥\\n\\n\";\n const logger = spinner(LOG_TITLE);\n if (enableLog) {\n logger.start();\n }\n\n const results: ToolCheckResult[] = [];\n let overallSuccess = true;\n let overallWarn = false;\n\n const tool_logs: string[] = [];\n\n for (const [index, tool] of config.entries()) {\n const TOOL_LOG_TITLE = `${blue(`[${tool.id}]`)} ${cyan(tool.displayName)}`;\n const SUCCESS_MARK = () => CHECK_MARK;\n const FAIL_MARK = () => {\n overallWarn = true;\n return tool.optional ? WARN_MARK : CROSS_MARK;\n };\n const setToolLog = (update: (cur: string) => string | (string | undefined | null)[]) => {\n const log = update(tool_logs[index] ?? \"\");\n tool_logs[index] = (Array.isArray(log) ? iter_map_not_null(log, (v) => (v ? v : null)) : [log]).map((line) => \" \" + line).join(\"\\n\");\n logger.text = LOG_TITLE + tool_logs.join(\"\\n\");\n };\n setToolLog(() => `Checking ${TOOL_LOG_TITLE}... `);\n let tool_log: (string | undefined | null)[] = [];\n\n const result: ToolCheckResult = {\n id: tool.id,\n displayName: tool.displayName,\n exists: false,\n meetsVersionRequirement: false, // Assume failure until proven otherwise\n isOptional: !!tool.optional,\n message: \"\",\n requiredVersion: tool.minVersion,\n installationHint: tool.installationHint,\n };\n\n const execResult = await executeCommand(tool.versionCommand);\n\n if (execResult.error || execResult.stderr.includes(\"command not found\") || execResult.stderr.includes(\"not recognized\")) {\n result.exists = false;\n result.message = `'${tool.id}' command not found or failed to execute.`;\n tool_log = [\n //\n `${FAIL_MARK()} ${TOOL_LOG_TITLE}`,\n ` ${red(result.message)}`,\n tool.installationHint && ` ${yellow(\"Hint:\")} ${tool.installationHint}`,\n ];\n } else {\n result.exists = true;\n const output = execResult.stdout.trim();\n const match = output.match(tool.versionParseRegex);\n\n if (match && match[1]) {\n result.version = semver.clean(match[1]) || undefined; // Clean the version string\n if (result.version) {\n if (tool.minVersion) {\n if (semver.gte(result.version, tool.minVersion)) {\n result.meetsVersionRequirement = true;\n result.message = `Version ${result.version} satisfies >=${tool.minVersion}.`;\n tool_log.push(`${SUCCESS_MARK()} ${TOOL_LOG_TITLE} (v${result.version})`);\n } else {\n result.meetsVersionRequirement = false;\n result.message = `Version ${result.version} is older than required >=${tool.minVersion}.`;\n tool_log.push(`${FAIL_MARK()} ${TOOL_LOG_TITLE} (v${result.version} - required: >=${tool.minVersion})`);\n tool_log.push(` ${red(result.message)}`);\n if (tool.installationHint) {\n tool_log.push(` ${yellow(\"Hint:\")} ${tool.installationHint}`);\n }\n }\n } else {\n // No minimum version specified, just existence is enough\n result.meetsVersionRequirement = true;\n result.message = `Found version ${result.version}. No minimum version specified.`;\n tool_log.push(`${SUCCESS_MARK()} ${TOOL_LOG_TITLE} (v${result.version} - existence check only)`);\n }\n } else {\n // Regex matched but couldn't clean version (should be rare with semver.clean)\n result.meetsVersionRequirement = false;\n result.message = `Could not parse a valid version string from output: \"${output}\". Regex: ${tool.versionParseRegex}`;\n tool_log.push(`${FAIL_MARK()} ${TOOL_LOG_TITLE}`);\n tool_log.push(` ${red(result.message)}`);\n }\n } else {\n result.meetsVersionRequirement = false;\n result.message = `Could not parse version from output: \"${output}\". Regex: ${tool.versionParseRegex}`;\n tool_log.push(`${FAIL_MARK}`);\n tool_log.push(` ${red(result.message)}`);\n }\n }\n\n setToolLog(() => tool_log);\n\n results.push(result);\n if (!result.meetsVersionRequirement && !result.isOptional) {\n overallSuccess = false;\n }\n }\n\n const LOG_SUMMERY = `${overallSuccess ? (overallWarn ? \"⚠️ \" : \"✅\") : \"💊\"} JIXO Environment Doctor 🏥\\n\\n`;\n logger.stopAndPersist({\n text: LOG_SUMMERY + tool_logs.join(\"\\n\") + \"\\n\",\n });\n\n return {\n overallSuccess,\n results,\n };\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"doctor.test.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/doctor.test.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
// Example Usage (e.g., in an index.ts or app.ts)
|
2
|
+
import { myDoctorConfig } from "./config.js"; // Assuming config.ts
|
3
|
+
import { runDoctor } from "./doctor.js";
|
4
|
+
async function main() {
|
5
|
+
await runDoctor(myDoctorConfig);
|
6
|
+
// console.log("\n\n--- Structured Report ---");
|
7
|
+
// console.log(JSON.stringify(report, null, 2));
|
8
|
+
// if (!report.overallSuccess) {
|
9
|
+
// console.error(bgRed(white("\nCritical environment checks failed. Please fix the issues above before proceeding.")));
|
10
|
+
// // process.exit(1); // Optionally exit if critical checks fail
|
11
|
+
// }
|
12
|
+
}
|
13
|
+
main().catch(console.error);
|
14
|
+
//# sourceMappingURL=doctor.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"doctor.test.js","sourceRoot":"","sources":["../../../src/commands/doctor/doctor.test.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,OAAO,EAAC,cAAc,EAAC,MAAM,aAAa,CAAC,CAAC,qBAAqB;AACjE,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtC,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,CAAC,cAAc,CAAC,CAAC;IAChC,kDAAkD;IAClD,kDAAkD;IAElD,kCAAkC;IAClC,2HAA2H;IAC3H,qEAAqE;IACrE,MAAM;AACR,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC","sourcesContent":["// Example Usage (e.g., in an index.ts or app.ts)\n\nimport {myDoctorConfig} from \"./config.js\"; // Assuming config.ts\nimport {runDoctor} from \"./doctor.js\";\n\nasync function main() {\n await runDoctor(myDoctorConfig);\n // console.log(\"\\n\\n--- Structured Report ---\");\n // console.log(JSON.stringify(report, null, 2));\n\n // if (!report.overallSuccess) {\n // console.error(bgRed(white(\"\\nCritical environment checks failed. Please fix the issues above before proceeding.\")));\n // // process.exit(1); // Optionally exit if critical checks fail\n // }\n}\n\nmain().catch(console.error);\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,MAAM,mDAAmC,OAAO,mHAe3D,CAAC"}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
// import {bgGreen, bgRed, black, white} from "@gaubee/nodekit"; // For the final message
|
2
|
+
import { func_remember } from "@gaubee/util";
|
3
|
+
import { myDoctorConfig } from "./config.js";
|
4
|
+
import { runDoctor } from "./doctor.js";
|
5
|
+
export const doctor = func_remember(async (enableLog = true) => {
|
6
|
+
const report = await runDoctor(myDoctorConfig, enableLog);
|
7
|
+
// if (log) {
|
8
|
+
// console.log("\n\n--- Structured Report (for programmatic use) ---");
|
9
|
+
// console.log(JSON.stringify(report, null, 2));
|
10
|
+
// if (!report.overallSuccess) {
|
11
|
+
// console.error(bgRed(white("\nCritical environment checks failed. Please fix the issues above before proceeding.")));
|
12
|
+
// // process.exit(1); // Optionally exit if critical checks fail in a real CLI
|
13
|
+
// } else {
|
14
|
+
// console.log(bgGreen(black("\nAll critical checks passed successfully!")));
|
15
|
+
// }
|
16
|
+
// }
|
17
|
+
return report;
|
18
|
+
});
|
19
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,OAAO,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAC,cAAc,EAAC,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtC,MAAM,CAAC,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,YAAqB,IAAI,EAAE,EAAE;IACtE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IAE1D,eAAe;IACf,2EAA2E;IAC3E,oDAAoD;IAEpD,oCAAoC;IACpC,6HAA6H;IAC7H,qFAAqF;IACrF,eAAe;IACf,mFAAmF;IACnF,QAAQ;IACR,MAAM;IACN,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC,CAAC","sourcesContent":["// import {bgGreen, bgRed, black, white} from \"@gaubee/nodekit\"; // For the final message\nimport {func_remember} from \"@gaubee/util\";\nimport {myDoctorConfig} from \"./config.js\";\nimport {runDoctor} from \"./doctor.js\";\n\nexport const doctor = func_remember(async (enableLog: boolean = true) => {\n const report = await runDoctor(myDoctorConfig, enableLog);\n\n // if (log) {\n // console.log(\"\\n\\n--- Structured Report (for programmatic use) ---\");\n // console.log(JSON.stringify(report, null, 2));\n\n // if (!report.overallSuccess) {\n // console.error(bgRed(white(\"\\nCritical environment checks failed. Please fix the issues above before proceeding.\")));\n // // process.exit(1); // Optionally exit if critical checks fail in a real CLI\n // } else {\n // console.log(bgGreen(black(\"\\nAll critical checks passed successfully!\")));\n // }\n // }\n return report;\n});\n"]}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
export interface ToolCheckConfig {
|
2
|
+
/** A unique identifier for this check (e.g., 'pnpm', 'uvx-cli') */
|
3
|
+
id: string;
|
4
|
+
/** User-friendly name for display purposes (e.g., "PNPM Package Manager") */
|
5
|
+
displayName: string;
|
6
|
+
/** The command to execute to get the version (e.g., "pnpm --version") */
|
7
|
+
versionCommand: string;
|
8
|
+
/**
|
9
|
+
* A regular expression to parse the version string from the command's output.
|
10
|
+
* It MUST have at least one capturing group, which should capture the version string.
|
11
|
+
* Example: For "pnpm 10.11.0", regex could be /pnpm\s+([\d.]+)/ or simply /([\d.]+)/
|
12
|
+
*/
|
13
|
+
versionParseRegex: RegExp;
|
14
|
+
/**
|
15
|
+
* The minimum required version (Semantic Versioning string).
|
16
|
+
* If undefined, only existence is checked.
|
17
|
+
*/
|
18
|
+
minVersion?: string;
|
19
|
+
/**
|
20
|
+
* Optional: A hint or URL for installation if the tool is missing or version is too low.
|
21
|
+
*/
|
22
|
+
installationHint?: string;
|
23
|
+
/**
|
24
|
+
* Optional: If true, a failure for this tool won't cause the overall doctor check to fail.
|
25
|
+
* It will still be reported. Defaults to false.
|
26
|
+
*/
|
27
|
+
optional?: boolean;
|
28
|
+
}
|
29
|
+
export type DoctorConfig = ToolCheckConfig[];
|
30
|
+
//# sourceMappingURL=types.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IAEX,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IAEpB,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/commands/doctor/types.ts"],"names":[],"mappings":"AACA,2CAA2C","sourcesContent":["\n// types.ts (or directly in your doctor.ts)\n\nexport interface ToolCheckConfig {\n /** A unique identifier for this check (e.g., 'pnpm', 'uvx-cli') */\n id: string;\n\n /** User-friendly name for display purposes (e.g., \"PNPM Package Manager\") */\n displayName: string;\n\n /** The command to execute to get the version (e.g., \"pnpm --version\") */\n versionCommand: string;\n\n /**\n * A regular expression to parse the version string from the command's output.\n * It MUST have at least one capturing group, which should capture the version string.\n * Example: For \"pnpm 10.11.0\", regex could be /pnpm\\s+([\\d.]+)/ or simply /([\\d.]+)/\n */\n versionParseRegex: RegExp;\n\n /**\n * The minimum required version (Semantic Versioning string).\n * If undefined, only existence is checked.\n */\n minVersion?: string;\n\n /**\n * Optional: A hint or URL for installation if the tool is missing or version is too low.\n */\n installationHint?: string;\n\n /**\n * Optional: If true, a failure for this tool won't cause the overall doctor check to fail.\n * It will still be reported. Defaults to false.\n */\n optional?: boolean;\n}\n\nexport type DoctorConfig = ToolCheckConfig[];\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,IAAI,GAAI,KAAK,MAAM,SAyD/B,CAAC"}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import { writeJson, writeMarkdown, writeText } from "@gaubee/nodekit";
|
2
|
+
import { str_trim_indent } from "@gaubee/util";
|
3
|
+
import fs from "node:fs";
|
4
|
+
import path from "node:path";
|
5
|
+
import { safeEnv } from "../env.js";
|
6
|
+
export const init = (dir) => {
|
7
|
+
const jixoDirname = path.join(dir, ".jixo");
|
8
|
+
/// 创建 .jixo 目录
|
9
|
+
fs.mkdirSync(jixoDirname, { recursive: true });
|
10
|
+
{
|
11
|
+
/// .jixo/readme.task.md
|
12
|
+
const readmeTaskFilepath = path.join(jixoDirname, "readme.task.md");
|
13
|
+
if (!fs.existsSync(readmeTaskFilepath)) {
|
14
|
+
writeMarkdown(readmeTaskFilepath, str_trim_indent(`
|
15
|
+
<!-- 您可以自定义 readme.md 文件的格式 -->
|
16
|
+
请JIXO帮我生成或者追加 README 文件
|
17
|
+
`), {
|
18
|
+
agents: ["readme-writer"],
|
19
|
+
});
|
20
|
+
}
|
21
|
+
}
|
22
|
+
/// 配置文件
|
23
|
+
{
|
24
|
+
const jixoConfigFilepath = path.join(jixoDirname, "jixo.config.json");
|
25
|
+
if (!fs.existsSync(jixoConfigFilepath)) {
|
26
|
+
writeJson(jixoConfigFilepath, {
|
27
|
+
tasks: { type: "dir", dirname: ".jixo" },
|
28
|
+
});
|
29
|
+
}
|
30
|
+
}
|
31
|
+
/// .jixo.env
|
32
|
+
{
|
33
|
+
const jixoEnvFilepath = path.join(dir, ".jixo.env");
|
34
|
+
if (!fs.existsSync(jixoEnvFilepath)) {
|
35
|
+
writeText(jixoEnvFilepath, Object.keys(safeEnv)
|
36
|
+
.filter((key) => key.startsWith("JIXO_"))
|
37
|
+
.map((key) => `${key}=""`)
|
38
|
+
.join("\n"));
|
39
|
+
}
|
40
|
+
}
|
41
|
+
/// .gitignore
|
42
|
+
{
|
43
|
+
const gitignoreFilepath = path.join(dir, ".gitignore");
|
44
|
+
const gitignoreLines = (fs.existsSync(gitignoreFilepath) ? fs.readFileSync(gitignoreFilepath, "utf-8") : "").split(/\n+/);
|
45
|
+
let changed = false;
|
46
|
+
for (const line of ["*.memory.json", "memory.json", ".jixo.env"]) {
|
47
|
+
if (!gitignoreLines.includes(line)) {
|
48
|
+
gitignoreLines.unshift(line);
|
49
|
+
changed = true;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
if (changed) {
|
53
|
+
fs.writeFileSync(gitignoreFilepath, gitignoreLines.join("\n"));
|
54
|
+
}
|
55
|
+
}
|
56
|
+
};
|
57
|
+
//# sourceMappingURL=init.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,aAAa,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE;IAClC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC5C,eAAe;IACf,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAC7C,CAAC;QACC,wBAAwB;QACxB,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;QACpE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACvC,aAAa,CACX,kBAAkB,EAClB,eAAe,CAAC;;;SAGf,CAAC,EACF;gBACE,MAAM,EAAE,CAAC,eAAe,CAAC;aAC1B,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,QAAQ;IACR,CAAC;QACC,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QACtE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACvC,SAAS,CAAC,kBAAkB,EAAE;gBAC5B,KAAK,EAAE,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAC;aAClB,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,aAAa;IACb,CAAC;QACC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACpC,SAAS,CACP,eAAe,EACf,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;iBACjB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;iBACxC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC;iBACzB,IAAI,CAAC,IAAI,CAAC,CACd,CAAC;QACJ,CAAC;IACH,CAAC;IACD,cAAc;IACd,CAAC;QACC,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACvD,MAAM,cAAc,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1H,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC7B,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,EAAE,CAAC,aAAa,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;AACH,CAAC,CAAC","sourcesContent":["import {writeJson, writeMarkdown, writeText} from \"@gaubee/nodekit\";\nimport {str_trim_indent} from \"@gaubee/util\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type {JixoConfig} from \"../config.js\";\nimport {safeEnv} from \"../env.js\";\nexport const init = (dir: string) => {\n const jixoDirname = path.join(dir, \".jixo\");\n /// 创建 .jixo 目录\n fs.mkdirSync(jixoDirname, {recursive: true});\n {\n /// .jixo/readme.task.md\n const readmeTaskFilepath = path.join(jixoDirname, \"readme.task.md\");\n if (!fs.existsSync(readmeTaskFilepath)) {\n writeMarkdown(\n readmeTaskFilepath,\n str_trim_indent(`\n <!-- 您可以自定义 readme.md 文件的格式 -->\n 请JIXO帮我生成或者追加 README 文件\n `),\n {\n agents: [\"readme-writer\"],\n },\n );\n }\n }\n /// 配置文件\n {\n const jixoConfigFilepath = path.join(jixoDirname, \"jixo.config.json\");\n if (!fs.existsSync(jixoConfigFilepath)) {\n writeJson(jixoConfigFilepath, {\n tasks: {type: \"dir\", dirname: \".jixo\"},\n } satisfies JixoConfig);\n }\n }\n /// .jixo.env\n {\n const jixoEnvFilepath = path.join(dir, \".jixo.env\");\n if (!fs.existsSync(jixoEnvFilepath)) {\n writeText(\n jixoEnvFilepath,\n Object.keys(safeEnv)\n .filter((key) => key.startsWith(\"JIXO_\"))\n .map((key) => `${key}=\"\"`)\n .join(\"\\n\"),\n );\n }\n }\n /// .gitignore\n {\n const gitignoreFilepath = path.join(dir, \".gitignore\");\n const gitignoreLines = (fs.existsSync(gitignoreFilepath) ? fs.readFileSync(gitignoreFilepath, \"utf-8\") : \"\").split(/\\n+/);\n let changed = false;\n for (const line of [\"*.memory.json\", \"memory.json\", \".jixo.env\"]) {\n if (!gitignoreLines.includes(line)) {\n gitignoreLines.unshift(line);\n changed = true;\n }\n }\n if (changed) {\n fs.writeFileSync(gitignoreFilepath, gitignoreLines.join(\"\\n\"));\n }\n }\n};\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/prompts/list.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,qBASvB,CAAC"}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { cyan, gray } from "@gaubee/nodekit";
|
2
|
+
import { obj_props } from "@gaubee/util";
|
3
|
+
import { getPromptConfigs } from "../../helper/prompts-loader.js";
|
4
|
+
export const listPrompts = async () => {
|
5
|
+
const configs = await getPromptConfigs();
|
6
|
+
for (const key of obj_props(configs)) {
|
7
|
+
const config = configs[key];
|
8
|
+
console.log(`- ${cyan(key)}: ${gray(config.content.split("\n")[0])}...`);
|
9
|
+
if (config.data.parent.length) {
|
10
|
+
console.log(` parent: ${config.data.parent.map(cyan).join(", ")}`);
|
11
|
+
}
|
12
|
+
}
|
13
|
+
};
|
14
|
+
//# sourceMappingURL=list.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/prompts/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,gBAAgB,EAAC,MAAM,gCAAgC,CAAC;AAEhE,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;IACpC,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACzE,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;AACH,CAAC,CAAC","sourcesContent":["import {cyan, gray} from \"@gaubee/nodekit\";\nimport {obj_props} from \"@gaubee/util\";\nimport {getPromptConfigs} from \"../../helper/prompts-loader.js\";\n\nexport const listPrompts = async () => {\n const configs = await getPromptConfigs();\n for (const key of obj_props(configs)) {\n const config = configs[key];\n console.log(`- ${cyan(key)}: ${gray(config.content.split(\"\\n\")[0])}...`);\n if (config.data.parent.length) {\n console.log(` parent: ${config.data.parent.map(cyan).join(\", \")}`);\n }\n }\n};\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../../src/commands/prompts/upgrade.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,GAAU,KAAK,MAAM,EAAE,SAAS;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,kBAa9E,CAAC"}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { spinner, writeJson } from "@gaubee/nodekit";
|
2
|
+
export const upgradePrompts = async (dir, options) => {
|
3
|
+
// TODO 下载最新的提示词集合
|
4
|
+
const mirrorUrl = options.mirrorUrl || "https://jixo.ai/jixo-prompts.json";
|
5
|
+
const loading = spinner("Upgrading prompts");
|
6
|
+
loading.start("Downloading...");
|
7
|
+
// await delay(1000);
|
8
|
+
try {
|
9
|
+
const prompts = await fetch(mirrorUrl).then((res) => res.json());
|
10
|
+
loading.stopAndPersist({ symbol: "✅", text: "Download completed" });
|
11
|
+
writeJson(import.meta.resolve("jixo-prompts.json"), prompts);
|
12
|
+
}
|
13
|
+
catch (e) {
|
14
|
+
loading.stopAndPersist({ symbol: "❌", text: "Download failed" });
|
15
|
+
}
|
16
|
+
};
|
17
|
+
//# sourceMappingURL=upgrade.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../../src/commands/prompts/upgrade.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAEnD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,GAAW,EAAE,OAA6B,EAAE,EAAE;IACjF,kBAAkB;IAClB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,mCAAmC,CAAC;IAC3E,MAAM,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC7C,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAChC,uBAAuB;IACvB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACjE,OAAO,CAAC,cAAc,CAAC,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,oBAAoB,EAAC,CAAC,CAAC;QAClE,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,cAAc,CAAC,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,iBAAiB,EAAC,CAAC,CAAC;IACjE,CAAC;AACH,CAAC,CAAC","sourcesContent":["import {spinner, writeJson} from \"@gaubee/nodekit\";\n\nexport const upgradePrompts = async (dir: string, options: {mirrorUrl?: string}) => {\n // TODO 下载最新的提示词集合\n const mirrorUrl = options.mirrorUrl || \"https://jixo.ai/jixo-prompts.json\";\n const loading = spinner(\"Upgrading prompts\");\n loading.start(\"Downloading...\");\n // await delay(1000);\n try {\n const prompts = await fetch(mirrorUrl).then((res) => res.json());\n loading.stopAndPersist({symbol: \"✅\", text: \"Download completed\"});\n writeJson(import.meta.resolve(\"jixo-prompts.json\"), prompts);\n } catch (e) {\n loading.stopAndPersist({symbol: \"❌\", text: \"Download failed\"});\n }\n};\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,GAAG,GAAU,MAAM,MAAM,EAAE,SAAS;IAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAC,kBA6B3F,CAAC"}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import { FileEntry, Ignore, normalizeFilePath } from "@gaubee/nodekit";
|
2
|
+
import { loadConfig } from "../config.js";
|
3
|
+
import { findChangedFilesSinceCommit } from "../helper/find-changes.js";
|
4
|
+
import { resolveAiTasks } from "../helper/resolve-ai-tasks.js";
|
5
|
+
export const run = async (_cwd, options) => {
|
6
|
+
const cwd = normalizeFilePath(_cwd);
|
7
|
+
const config = await loadConfig(cwd);
|
8
|
+
const ai_tasks = resolveAiTasks(cwd, config.tasks);
|
9
|
+
const nameMatcher = options.nameFilter.length ? new Ignore(options.nameFilter, cwd) : { isMatch: () => true };
|
10
|
+
const dirMatcher = options.dirFilter.length ? new Ignore(options.dirFilter, cwd) : { isMatch: () => true };
|
11
|
+
const changedFiles = await findChangedFilesSinceCommit("@jixo", cwd);
|
12
|
+
// const run_tasks: Array<Func> = [];
|
13
|
+
for (const ai_task of ai_tasks) {
|
14
|
+
const { dir: task_dir } = ai_task;
|
15
|
+
if (!dirMatcher.isMatch(task_dir)) {
|
16
|
+
continue;
|
17
|
+
}
|
18
|
+
if (!nameMatcher.isMatch(ai_task.name)) {
|
19
|
+
continue;
|
20
|
+
}
|
21
|
+
let task_changedFiles = changedFiles;
|
22
|
+
if (task_dir !== cwd) {
|
23
|
+
task_changedFiles = task_changedFiles.filter((file) => file.path.startsWith(task_dir + "/"));
|
24
|
+
}
|
25
|
+
// run_tasks.push(() => runAiTask(ai_task, task_changedFiles));
|
26
|
+
await runAiTask(ai_task, task_changedFiles);
|
27
|
+
}
|
28
|
+
// let done_tasks = 0
|
29
|
+
// const running = spinner.default("running tasks...");
|
30
|
+
// func_parallel_limit(run_tasks, 5).watch(()=>{
|
31
|
+
// })
|
32
|
+
};
|
33
|
+
const runAiTask = async (ai_task, changedFiles) => {
|
34
|
+
console.log("run ai task");
|
35
|
+
};
|
36
|
+
//# sourceMappingURL=run.js.map
|