@jixo/cli 0.22.0 → 0.23.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.
Files changed (50) hide show
  1. package/bundle/index.js +251 -133
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +83 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/daemon.d.ts +5 -0
  7. package/dist/commands/daemon.d.ts.map +1 -0
  8. package/dist/commands/daemon.js +20 -0
  9. package/dist/commands/daemon.js.map +1 -0
  10. package/dist/commands/doctor/config.d.ts +3 -0
  11. package/dist/commands/doctor/config.d.ts.map +1 -0
  12. package/dist/commands/doctor/config.js +17 -0
  13. package/dist/commands/doctor/config.js.map +1 -0
  14. package/dist/commands/doctor/doctor.d.ts +3 -0
  15. package/dist/commands/doctor/doctor.d.ts.map +1 -0
  16. package/dist/commands/doctor/doctor.js +158 -0
  17. package/dist/commands/doctor/doctor.js.map +1 -0
  18. package/dist/commands/doctor/doctor.test.d.ts +2 -0
  19. package/dist/commands/doctor/doctor.test.d.ts.map +1 -0
  20. package/dist/commands/doctor/doctor.test.js +14 -0
  21. package/dist/commands/doctor/doctor.test.js.map +1 -0
  22. package/dist/commands/doctor/index.d.ts +2 -0
  23. package/dist/commands/doctor/index.d.ts.map +1 -0
  24. package/dist/commands/doctor/index.js +8 -0
  25. package/dist/commands/doctor/index.js.map +1 -0
  26. package/dist/commands/doctor/types.d.ts +45 -0
  27. package/dist/commands/doctor/types.d.ts.map +1 -0
  28. package/dist/commands/doctor/types.js +3 -0
  29. package/dist/commands/doctor/types.js.map +1 -0
  30. package/dist/commands/google-aistudio.d.ts.map +1 -1
  31. package/dist/commands/google-aistudio.js +29 -4
  32. package/dist/commands/google-aistudio.js.map +1 -1
  33. package/dist/commands/init.d.ts +2 -0
  34. package/dist/commands/init.d.ts.map +1 -0
  35. package/dist/commands/init.js +40 -0
  36. package/dist/commands/init.js.map +1 -0
  37. package/dist/commands/tasks/run.d.ts +10 -0
  38. package/dist/commands/tasks/run.d.ts.map +1 -0
  39. package/dist/commands/tasks/run.js +44 -0
  40. package/dist/commands/tasks/run.js.map +1 -0
  41. package/dist/config.d.ts +15 -0
  42. package/dist/config.d.ts.map +1 -0
  43. package/dist/config.js +23 -0
  44. package/dist/config.js.map +1 -0
  45. package/dist/env.d.ts +6 -0
  46. package/dist/env.d.ts.map +1 -0
  47. package/dist/env.js +16 -0
  48. package/dist/env.js.map +1 -0
  49. package/dist/prompts.json +14 -2
  50. package/package.json +5 -4
package/dist/cli.js ADDED
@@ -0,0 +1,83 @@
1
+ import { cwdResolver } from "@gaubee/node";
2
+ import yargs from "yargs";
3
+ import { hideBin } from "yargs/helpers";
4
+ import packageJson from "../package.json" with { type: "json" };
5
+ import { restartDaemon, startDaemon, statusDaemon, stopDaemon } from "./commands/daemon.js";
6
+ import { doctor } from "./commands/doctor/index.js";
7
+ import { init } from "./commands/init.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
+ .scriptName("jixo")
12
+ .version(packageJson.version)
13
+ .command("doctor", "Check the requirements and health of the JIXO environment", (yargs) => yargs, () => {
14
+ doctor();
15
+ })
16
+ .command("init [dir]", "Create a new JIXO project configuration", (yargs) => {
17
+ return yargs.positional("dir", {
18
+ describe: "The directory to create the JIXO config",
19
+ default: "./",
20
+ });
21
+ }, (argv) => {
22
+ init(cwdResolver(argv.dir));
23
+ })
24
+ .command("run <goal>", "Run a JIXO job with a specific goal", (yargs) => {
25
+ return yargs
26
+ .positional("goal", {
27
+ describe: "The high-level goal for the job",
28
+ type: "string",
29
+ demandOption: true,
30
+ })
31
+ .option("dir", {
32
+ alias: "D",
33
+ type: "string",
34
+ description: "The project directory to run in",
35
+ default: process.cwd(),
36
+ })
37
+ .option("loop", {
38
+ alias: "L",
39
+ type: "number",
40
+ description: "The max loop times for the job",
41
+ default: 20,
42
+ });
43
+ }, (argv) => {
44
+ run({
45
+ jobGoal: argv.goal,
46
+ workDir: cwdResolver(argv.dir),
47
+ maxLoops: argv.loop,
48
+ });
49
+ })
50
+ .command("daemon <action>", "Manage the JIXO Core daemon", (yargs) => {
51
+ return yargs.positional("action", {
52
+ describe: "The action to perform on the daemon",
53
+ type: "string",
54
+ choices: ["start", "stop", "status", "restart"],
55
+ demandOption: true,
56
+ });
57
+ }, (argv) => {
58
+ switch (argv.action) {
59
+ case "start":
60
+ startDaemon();
61
+ break;
62
+ case "stop":
63
+ stopDaemon();
64
+ break;
65
+ case "status":
66
+ statusDaemon();
67
+ break;
68
+ case "restart":
69
+ restartDaemon();
70
+ break;
71
+ }
72
+ })
73
+ .demandCommand(1, "You need at least one command before moving on")
74
+ .strict()
75
+ .help();
76
+ const argv = await cli.parse();
77
+ if (argv._.length === 0) {
78
+ cli.showHelp();
79
+ console.log(" " + "─".repeat(Math.max(4, process.stdout.columns - 2)));
80
+ await doctor();
81
+ }
82
+ };
83
+ //# sourceMappingURL=cli.js.map
@@ -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 packageJson from \"../package.json\" with {type: \"json\"};\nimport {restartDaemon, startDaemon, statusDaemon, stopDaemon} from \"./commands/daemon.js\";\nimport {doctor} from \"./commands/doctor/index.js\";\nimport {init} from \"./commands/init.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 .scriptName(\"jixo\")\n .version(packageJson.version)\n .command(\n \"doctor\",\n \"Check the requirements and health of the JIXO environment\",\n (yargs) => yargs,\n () => {\n doctor();\n },\n )\n .command(\n \"init [dir]\",\n \"Create a new JIXO project configuration\",\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 <goal>\",\n \"Run a JIXO job with a specific goal\",\n (yargs) => {\n return yargs\n .positional(\"goal\", {\n describe: \"The high-level goal for the job\",\n type: \"string\",\n demandOption: true,\n })\n .option(\"dir\", {\n alias: \"D\",\n type: \"string\",\n description: \"The project directory to run in\",\n default: process.cwd(),\n })\n .option(\"loop\", {\n alias: \"L\",\n type: \"number\",\n description: \"The max loop times for the job\",\n default: 20,\n });\n },\n (argv) => {\n run({\n jobGoal: argv.goal,\n workDir: cwdResolver(argv.dir),\n maxLoops: argv.loop,\n });\n },\n )\n .command(\n \"daemon <action>\",\n \"Manage the JIXO Core daemon\",\n (yargs) => {\n return yargs.positional(\"action\", {\n describe: \"The action to perform on the daemon\",\n type: \"string\",\n choices: [\"start\", \"stop\", \"status\", \"restart\"],\n demandOption: true,\n });\n },\n (argv) => {\n switch (argv.action) {\n case \"start\":\n startDaemon();\n break;\n case \"stop\":\n stopDaemon();\n break;\n case \"status\":\n statusDaemon();\n break;\n case \"restart\":\n restartDaemon();\n break;\n }\n },\n )\n .demandCommand(1, \"You need at least one command before moving on\")\n .strict()\n .help();\n\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 - 2)));\n await doctor();\n }\n};\n"]}
@@ -0,0 +1,5 @@
1
+ export declare const startDaemon: () => void;
2
+ export declare const stopDaemon: () => void;
3
+ export declare const statusDaemon: () => void;
4
+ export declare const restartDaemon: () => void;
5
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/commands/daemon.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW,YAGvB,CAAC;AAEF,eAAO,MAAM,UAAU,YAEtB,CAAC;AAEF,eAAO,MAAM,YAAY,YAGxB,CAAC;AAEF,eAAO,MAAM,aAAa,YAIzB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { green, red, yellow } from "@gaubee/nodekit";
2
+ // NOTE: This is a placeholder implementation. A robust solution would use
3
+ // libraries like 'pm2', 'forever', or manage PID files directly.
4
+ export const startDaemon = () => {
5
+ console.log(green("Starting JIXO Core service in the background... (stub)"));
6
+ console.log(yellow("In a real implementation, this would spawn the core service process."));
7
+ };
8
+ export const stopDaemon = () => {
9
+ console.log(red("Stopping JIXO Core service... (stub)"));
10
+ };
11
+ export const statusDaemon = () => {
12
+ console.log(yellow("Checking JIXO Core service status... (stub)"));
13
+ console.log("Service is not running (default stub response).");
14
+ };
15
+ export const restartDaemon = () => {
16
+ console.log(yellow("Restarting JIXO Core service... (stub)"));
17
+ stopDaemon();
18
+ startDaemon();
19
+ };
20
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/commands/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAC,MAAM,iBAAiB,CAAC;AAEnD,0EAA0E;AAC1E,iEAAiE;AAEjE,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE;IAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC,CAAC;IAC7E,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,sEAAsE,CAAC,CAAC,CAAC;AAC9F,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE;IAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,EAAE;IAC/B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,6CAA6C,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;AACjE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE;IAChC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,wCAAwC,CAAC,CAAC,CAAC;IAC9D,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,CAAC;AAChB,CAAC,CAAC","sourcesContent":["import {green, red, yellow} from \"@gaubee/nodekit\";\n\n// NOTE: This is a placeholder implementation. A robust solution would use\n// libraries like 'pm2', 'forever', or manage PID files directly.\n\nexport const startDaemon = () => {\n console.log(green(\"Starting JIXO Core service in the background... (stub)\"));\n console.log(yellow(\"In a real implementation, this would spawn the core service process.\"));\n};\n\nexport const stopDaemon = () => {\n console.log(red(\"Stopping JIXO Core service... (stub)\"));\n};\n\nexport const statusDaemon = () => {\n console.log(yellow(\"Checking JIXO Core service status... (stub)\"));\n console.log(\"Service is not running (default stub response).\");\n};\n\nexport const restartDaemon = () => {\n console.log(yellow(\"Restarting JIXO Core service... (stub)\"));\n stopDaemon();\n startDaemon();\n};\n"]}
@@ -0,0 +1,3 @@
1
+ import type { DoctorConfig } from "./types.js";
2
+ export declare const myDoctorConfig: DoctorConfig;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -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;AAE7C,eAAO,MAAM,cAAc,EAAE,YAc5B,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { blue, green } from "@gaubee/nodekit";
2
+ export const myDoctorConfig = [
3
+ {
4
+ id: "jixo-core-service",
5
+ displayName: "JIXO Core Service",
6
+ installationHint: `Ensure the JIXO Core service is running. You can start it with 'jixo daemon start'.`,
7
+ },
8
+ {
9
+ id: "pnpm",
10
+ displayName: "PNPM Package Manager",
11
+ versionCommand: "pnpm --version",
12
+ versionParseRegex: /(\d+\.\d+\.\d+)/, // Assumes pnpm --version outputs just the version or "X.Y.Z ..."
13
+ minVersion: "10.9.0",
14
+ installationHint: `Install pnpm via npm: ${green("npm install -g pnpm")}. Or visit ${blue("https://pnpm.io/installation")}`,
15
+ },
16
+ ];
17
+ //# 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;AAG5C,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C;QACE,EAAE,EAAE,mBAAmB;QACvB,WAAW,EAAE,mBAAmB;QAChC,gBAAgB,EAAE,qFAAqF;KACxG;IACD;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;CACF,CAAC","sourcesContent":["import {blue, green} from \"@gaubee/nodekit\";\nimport type {DoctorConfig} from \"./types.js\";\n\nexport const myDoctorConfig: DoctorConfig = [\n {\n id: \"jixo-core-service\",\n displayName: \"JIXO Core Service\",\n installationHint: `Ensure the JIXO Core service is running. You can start it with 'jixo daemon start'.`,\n },\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"]}
@@ -0,0 +1,3 @@
1
+ import type { DoctorConfig, DoctorReport } from "./types.js";
2
+ export declare function runDoctor(config: DoctorConfig, enableLog?: boolean): Promise<DoctorReport>;
3
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/doctor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,YAAY,EAAE,YAAY,EAAkB,MAAM,YAAY,CAAC;AA4C5E,wBAAsB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,GAAE,OAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAkHtG"}
@@ -0,0 +1,158 @@
1
+ import { blue, cyan, green, red, spinner, yellow } from "@gaubee/nodekit";
2
+ import { iter_map_not_null } from "@gaubee/util";
3
+ import { execSync } from "node:child_process";
4
+ import semver from "semver";
5
+ import { safeEnv } from "../../env.js";
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
+ async function checkServiceHealth(id, displayName, hint) {
21
+ const result = {
22
+ id,
23
+ displayName,
24
+ exists: false,
25
+ meetsVersionRequirement: false,
26
+ isOptional: false,
27
+ message: "",
28
+ installationHint: hint,
29
+ };
30
+ const url = `${safeEnv.JIXO_CORE_URL}/jixo/v1/health`;
31
+ try {
32
+ const response = await fetch(url, { signal: AbortSignal.timeout(3000) });
33
+ if (response.ok) {
34
+ result.exists = true;
35
+ result.meetsVersionRequirement = true;
36
+ result.message = `Service is running and healthy at ${url}`;
37
+ }
38
+ else {
39
+ result.message = `Service responded with status ${response.status} at ${url}`;
40
+ }
41
+ }
42
+ catch (e) {
43
+ result.message = `Could not connect to service at ${url}. Is it running?`;
44
+ }
45
+ return result;
46
+ }
47
+ export async function runDoctor(config, enableLog = true) {
48
+ const LOG_TITLE = "Running Environment Doctor 🏥\n\n";
49
+ const logger = spinner(LOG_TITLE);
50
+ if (enableLog) {
51
+ logger.start();
52
+ }
53
+ const results = [];
54
+ let overallSuccess = true;
55
+ let overallWarn = false;
56
+ const tool_logs = [];
57
+ for (const [index, tool] of config.entries()) {
58
+ const TOOL_LOG_TITLE = `${blue(`[${tool.id}]`)} ${cyan(tool.displayName)}`;
59
+ const SUCCESS_MARK = () => CHECK_MARK;
60
+ const FAIL_MARK = () => {
61
+ overallWarn = true;
62
+ return tool.optional ? WARN_MARK : CROSS_MARK;
63
+ };
64
+ const setToolLog = (update) => {
65
+ const log = update(tool_logs[index] ?? "");
66
+ tool_logs[index] = (Array.isArray(log) ? iter_map_not_null(log, (v) => (v ? v : null)) : [log]).map((line) => " " + line).join("\n");
67
+ logger.text = LOG_TITLE + tool_logs.join("\n");
68
+ };
69
+ setToolLog(() => `Checking ${TOOL_LOG_TITLE}... `);
70
+ let tool_log = [];
71
+ let result;
72
+ if (!tool.versionCommand) {
73
+ // Custom check logic for services
74
+ result = await checkServiceHealth(tool.id, tool.displayName, tool.installationHint);
75
+ if (result.exists) {
76
+ tool_log = [`${SUCCESS_MARK()} ${TOOL_LOG_TITLE}`, ` ${green(result.message)}`];
77
+ }
78
+ else {
79
+ tool_log = [`${FAIL_MARK()} ${TOOL_LOG_TITLE}`, ` ${red(result.message)}`, tool.installationHint && ` ${yellow("Hint:")} ${tool.installationHint}`];
80
+ }
81
+ }
82
+ else {
83
+ // Original command-based check logic
84
+ result = {
85
+ id: tool.id,
86
+ displayName: tool.displayName,
87
+ exists: false,
88
+ meetsVersionRequirement: false,
89
+ isOptional: !!tool.optional,
90
+ message: "",
91
+ requiredVersion: tool.minVersion,
92
+ installationHint: tool.installationHint,
93
+ };
94
+ const execResult = await executeCommand(tool.versionCommand);
95
+ if (execResult.error || execResult.stderr.includes("command not found") || execResult.stderr.includes("not recognized")) {
96
+ result.exists = false;
97
+ result.message = `'${tool.id}' command not found or failed to execute.`;
98
+ tool_log = [`${FAIL_MARK()} ${TOOL_LOG_TITLE}`, ` ${red(result.message)}`, tool.installationHint && ` ${yellow("Hint:")} ${tool.installationHint}`];
99
+ }
100
+ else {
101
+ result.exists = true;
102
+ const output = execResult.stdout.trim();
103
+ const match = output.match(tool.versionParseRegex);
104
+ if (match && match[1]) {
105
+ result.version = semver.clean(match[1]) || undefined;
106
+ if (result.version) {
107
+ if (tool.minVersion) {
108
+ if (semver.gte(result.version, tool.minVersion)) {
109
+ result.meetsVersionRequirement = true;
110
+ result.message = `Version ${result.version} satisfies >=${tool.minVersion}.`;
111
+ tool_log.push(`${SUCCESS_MARK()} ${TOOL_LOG_TITLE} (v${result.version})`);
112
+ }
113
+ else {
114
+ result.meetsVersionRequirement = false;
115
+ result.message = `Version ${result.version} is older than required >=${tool.minVersion}.`;
116
+ tool_log.push(`${FAIL_MARK()} ${TOOL_LOG_TITLE} (v${result.version} - required: >=${tool.minVersion})`);
117
+ if (tool.installationHint) {
118
+ tool_log.push(` ${yellow("Hint:")} ${tool.installationHint}`);
119
+ }
120
+ }
121
+ }
122
+ else {
123
+ result.meetsVersionRequirement = true;
124
+ result.message = `Found version ${result.version}. No minimum version specified.`;
125
+ tool_log.push(`${SUCCESS_MARK()} ${TOOL_LOG_TITLE} (v${result.version} - existence check only)`);
126
+ }
127
+ }
128
+ else {
129
+ result.meetsVersionRequirement = false;
130
+ result.message = `Could not parse a valid version string from output: "${output}".`;
131
+ tool_log.push(`${FAIL_MARK()} ${TOOL_LOG_TITLE}`);
132
+ tool_log.push(` ${red(result.message)}`);
133
+ }
134
+ }
135
+ else {
136
+ result.meetsVersionRequirement = false;
137
+ result.message = `Could not parse version from output: "${output}".`;
138
+ tool_log.push(`${FAIL_MARK()} ${TOOL_LOG_TITLE}`);
139
+ tool_log.push(` ${red(result.message)}`);
140
+ }
141
+ }
142
+ }
143
+ setToolLog(() => tool_log);
144
+ results.push(result);
145
+ if (!result.meetsVersionRequirement && !result.isOptional) {
146
+ overallSuccess = false;
147
+ }
148
+ }
149
+ const LOG_SUMMERY = `${overallSuccess ? (overallWarn ? "⚠️ " : "✅") : "💊"} JIXO Environment Doctor 🏥\n\n`;
150
+ logger.stopAndPersist({
151
+ text: LOG_SUMMERY + tool_logs.join("\n") + "\n",
152
+ });
153
+ return {
154
+ overallSuccess,
155
+ results,
156
+ };
157
+ }
158
+ //# 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":["import {blue, cyan, green, red, spinner, yellow} from \"@gaubee/nodekit\";\nimport {iter_map_not_null} from \"@gaubee/util\";\nimport {execSync} from \"node:child_process\";\nimport semver from \"semver\";\nimport {safeEnv} from \"../../env.js\";\nimport type {DoctorConfig, DoctorReport, ToolCheckResult} from \"./types.js\";\n\nconst CHECK_MARK = green(\"✔\");\nconst CROSS_MARK = red(\"✖\");\nconst WARN_MARK = yellow(\"⚠\");\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\nasync function checkServiceHealth(id: string, displayName: string, hint?: string): Promise<ToolCheckResult> {\n const result: ToolCheckResult = {\n id,\n displayName,\n exists: false,\n meetsVersionRequirement: false,\n isOptional: false,\n message: \"\",\n installationHint: hint,\n };\n\n const url = `${safeEnv.JIXO_CORE_URL}/jixo/v1/health`;\n try {\n const response = await fetch(url, {signal: AbortSignal.timeout(3000)});\n if (response.ok) {\n result.exists = true;\n result.meetsVersionRequirement = true;\n result.message = `Service is running and healthy at ${url}`;\n } else {\n result.message = `Service responded with status ${response.status} at ${url}`;\n }\n } catch (e) {\n result.message = `Could not connect to service at ${url}. Is it running?`;\n }\n return result;\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 let result: ToolCheckResult;\n\n if (!tool.versionCommand) {\n // Custom check logic for services\n result = await checkServiceHealth(tool.id, tool.displayName, tool.installationHint);\n if (result.exists) {\n tool_log = [`${SUCCESS_MARK()} ${TOOL_LOG_TITLE}`, ` ${green(result.message)}`];\n } else {\n tool_log = [`${FAIL_MARK()} ${TOOL_LOG_TITLE}`, ` ${red(result.message)}`, tool.installationHint && ` ${yellow(\"Hint:\")} ${tool.installationHint}`];\n }\n } else {\n // Original command-based check logic\n result = {\n id: tool.id,\n displayName: tool.displayName,\n exists: false,\n meetsVersionRequirement: false,\n isOptional: !!tool.optional,\n message: \"\",\n requiredVersion: tool.minVersion,\n installationHint: tool.installationHint,\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 = [`${FAIL_MARK()} ${TOOL_LOG_TITLE}`, ` ${red(result.message)}`, tool.installationHint && ` ${yellow(\"Hint:\")} ${tool.installationHint}`];\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;\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 if (tool.installationHint) {\n tool_log.push(` ${yellow(\"Hint:\")} ${tool.installationHint}`);\n }\n }\n } else {\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 result.meetsVersionRequirement = false;\n result.message = `Could not parse a valid version string from output: \"${output}\".`;\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}\".`;\n tool_log.push(`${FAIL_MARK()} ${TOOL_LOG_TITLE}`);\n tool_log.push(` ${red(result.message)}`);\n }\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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=doctor.test.d.ts.map
@@ -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,2 @@
1
+ export declare const doctor: import("@gaubee/util").FuncRemember<(enableLog?: boolean) => Promise<import("./types.js").DoctorReport>, void | ((this: unknown, enableLog?: boolean | undefined) => any)>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,mDAAmC,OAAO,kHAG3D,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { func_remember } from "@gaubee/util";
2
+ import { myDoctorConfig } from "./config.js";
3
+ import { runDoctor } from "./doctor.js";
4
+ export const doctor = func_remember(async (enableLog = true) => {
5
+ const report = await runDoctor(myDoctorConfig, enableLog);
6
+ return report;
7
+ });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAAA,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;IAC1D,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC,CAAC","sourcesContent":["import {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 return report;\n});\n"]}
@@ -0,0 +1,45 @@
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
+ export interface ToolCheckResult {
31
+ id: string;
32
+ displayName: string;
33
+ exists: boolean;
34
+ version?: string;
35
+ requiredVersion?: string;
36
+ meetsVersionRequirement: boolean;
37
+ isOptional: boolean;
38
+ message: string;
39
+ installationHint?: string;
40
+ }
41
+ export interface DoctorReport {
42
+ overallSuccess: boolean;
43
+ results: ToolCheckResult[];
44
+ }
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IAEX,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IAEpB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;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;AAE7C,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"}
@@ -0,0 +1,3 @@
1
+ // types.ts (or directly in your doctor.ts)
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/commands/doctor/types.ts"],"names":[],"mappings":"AAAA,2CAA2C","sourcesContent":["// 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\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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"google-aistudio.d.ts","sourceRoot":"","sources":["../../src/commands/google-aistudio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAY,aAAa,EAAC,MAAM,OAAO,CAAC;AA+DpD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,CAU/D,CAAC"}
1
+ {"version":3,"file":"google-aistudio.d.ts","sourceRoot":"","sources":["../../src/commands/google-aistudio.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAY,aAAa,EAAC,MAAM,OAAO,CAAC;AAoFpD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,aAAa,CAAC,MAAM,EAAE,MAAM,CAiB/D,CAAC"}
@@ -1,8 +1,9 @@
1
- import { doGoogleAiStudioAutomation, doSync } from "@jixo/dev/google-aistudio";
1
+ import { doGoogleAiStudioAutomation, doInit, doSync } from "@jixo/dev/google-aistudio";
2
+ import path from "node:path";
2
3
  // 定义 'sync' 子命令
3
4
  const syncCommand = {
4
5
  command: "sync [path]",
5
- aliases: ["S"],
6
+ aliases: ["S", "s"],
6
7
  describe: "Sync with aistudio.google.com contents",
7
8
  builder: (yargs) => yargs
8
9
  .positional("path", {
@@ -34,7 +35,7 @@ const syncCommand = {
34
35
  };
35
36
  const browserCommand = {
36
37
  command: "browser [dir]",
37
- aliases: ["B"],
38
+ aliases: ["B", "b"],
38
39
  describe: "browser-kit for aistudio.google.com",
39
40
  builder: (yargs) => yargs.positional("dir", {
40
41
  describe: "Directory for aistudio output contents",
@@ -45,6 +46,25 @@ const browserCommand = {
45
46
  doGoogleAiStudioAutomation(argv.dir);
46
47
  },
47
48
  };
49
+ const initCommand = {
50
+ command: "init [dir]",
51
+ aliases: ["i", "I"],
52
+ describe: "init an browser-kit directory for aistudio.google.com",
53
+ builder: (yargs) => yargs
54
+ .positional("dir", {
55
+ describe: "Directory for aistudio input/output contents",
56
+ type: "string",
57
+ default: path.resolve(process.cwd(), ".ai"),
58
+ })
59
+ .option("force", {
60
+ alias: "F",
61
+ type: "boolean",
62
+ describe: "override exits files",
63
+ }),
64
+ handler: async (argv) => {
65
+ doInit(argv);
66
+ },
67
+ };
48
68
  /**
49
69
  * @jixo/cli google-aistudio
50
70
  *
@@ -56,7 +76,12 @@ export const googleAistudioCommand = {
56
76
  describe: "Commands for Google AI Studio integration",
57
77
  builder: (yargs) => {
58
78
  // 将 syncCommand 注册为 google-aistudio 的子命令
59
- return yargs.command(syncCommand).command(browserCommand).demandCommand(1, "You must provide a sub-command for 'google-aistudio'.");
79
+ return (yargs
80
+ .command(syncCommand)
81
+ .command(browserCommand)
82
+ .command(initCommand)
83
+ //
84
+ .demandCommand(1, "You must provide a sub-command for 'google-aistudio'."));
60
85
  },
61
86
  // 这个 handler 理论上不会被执行,因为 yargs 会要求一个子命令
62
87
  handler: () => { },
@@ -1 +1 @@
1
- {"version":3,"file":"google-aistudio.js","sourceRoot":"","sources":["../../src/commands/google-aistudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,0BAA0B,EAAE,MAAM,EAAmB,MAAM,2BAA2B,CAAC;AAU/F,gBAAgB;AAChB,MAAM,WAAW,GAAoC;IACnD,OAAO,EAAE,aAAa;IACtB,OAAO,EAAE,CAAC,GAAG,CAAC;IACd,QAAQ,EAAE,wCAAwC;IAClD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,QAAQ,EAAE,gCAAgC;QAC1C,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE;KACvB,CAAC;SACD,MAAM,CAAC,OAAO,EAAE;QACf,KAAK,EAAE,GAAG;QACV,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,+CAA+C;QACzD,OAAO,EAAE,KAAK;KACf,CAAC;SACD,MAAM,CAAC,QAAQ,EAAE;QAChB,KAAK,EAAE,GAAG;QACV,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,2DAA2D;KACtE,CAAC;IACN,OAAO,EAAE,KAAK,EAAE,IAAyB,EAAE,EAAE;QAC3C,mCAAmC;QACnC,4CAA4C;QAC5C,qBAAqB;QACrB,MAAM,gBAAgB,GAAgB;YACpC,GAAG,IAAI;YACP,CAAC,EAAE,CAAC,IAAI,CAAC,IAAc,CAAC;SACzB,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC3B,CAAC;CACF,CAAC;AAMF,MAAM,cAAc,GAAuC;IACzD,OAAO,EAAE,eAAe;IACxB,OAAO,EAAE,CAAC,GAAG,CAAC;IACd,QAAQ,EAAE,qCAAqC;IAC/C,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE;QACtB,QAAQ,EAAE,wCAAwC;QAClD,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE;KACvB,CAAC;IACJ,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAkC;IAClE,OAAO,EAAE,2BAA2B;IACpC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;IAC3B,QAAQ,EAAE,2CAA2C;IACrD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACjB,yCAAyC;QACzC,OAAO,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,uDAAuD,CAAC,CAAC;IACtI,CAAC;IACD,wCAAwC;IACxC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;CAClB,CAAC","sourcesContent":["import {doGoogleAiStudioAutomation, doSync, type SyncOptions} from \"@jixo/dev/google-aistudio\";\nimport type {Arguments, CommandModule} from \"yargs\";\n\n// 定义 yargs builder 所需的参数接口\ninterface SyncArgs {\n path?: string;\n watch?: boolean;\n outDir?: string;\n}\n\n// 定义 'sync' 子命令\nconst syncCommand: CommandModule<object, SyncArgs> = {\n command: \"sync [path]\",\n aliases: [\"S\"],\n describe: \"Sync with aistudio.google.com contents\",\n builder: (yargs) =>\n yargs\n .positional(\"path\", {\n describe: \"Directory or file path to sync\",\n type: \"string\",\n default: process.cwd(),\n })\n .option(\"watch\", {\n alias: \"W\",\n type: \"boolean\",\n describe: \"Watch for file changes and sync automatically\",\n default: false,\n })\n .option(\"outDir\", {\n alias: \"O\",\n type: \"string\",\n describe: \"Specify the output directory for generated markdown files\",\n }),\n handler: async (argv: Arguments<SyncArgs>) => {\n // 将 yargs 的解析结果适配为 doSync 函数期望的格式。\n // 关键是 yargs 的位置参数是命名好的 (argv.path),而 doSync\n // 期望它在 `_` 数组的第一个位置。\n const optionsForDoSync: SyncOptions = {\n ...argv,\n _: [argv.path as string],\n };\n doSync(optionsForDoSync);\n },\n};\n\ninterface BrowserArgs {\n dir?: string;\n}\n\nconst browserCommand: CommandModule<object, BrowserArgs> = {\n command: \"browser [dir]\",\n aliases: [\"B\"],\n describe: \"browser-kit for aistudio.google.com\",\n builder: (yargs) =>\n yargs.positional(\"dir\", {\n describe: \"Directory for aistudio output contents\",\n type: \"string\",\n default: process.cwd(),\n }),\n handler: async (argv) => {\n doGoogleAiStudioAutomation(argv.dir);\n },\n};\n\n/**\n * @jixo/cli google-aistudio\n *\n * Group of commands for interacting with Google AI Studio.\n */\nexport const googleAistudioCommand: CommandModule<object, object> = {\n command: \"google-aistudio <command>\",\n aliases: [\"GO\", \"Go\", \"go\"],\n describe: \"Commands for Google AI Studio integration\",\n builder: (yargs) => {\n // 将 syncCommand 注册为 google-aistudio 的子命令\n return yargs.command(syncCommand).command(browserCommand).demandCommand(1, \"You must provide a sub-command for 'google-aistudio'.\");\n },\n // 这个 handler 理论上不会被执行,因为 yargs 会要求一个子命令\n handler: () => {},\n};\n"]}
1
+ {"version":3,"file":"google-aistudio.js","sourceRoot":"","sources":["../../src/commands/google-aistudio.ts"],"names":[],"mappings":"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","sourcesContent":["import {doGoogleAiStudioAutomation, doInit, doSync, type InitOptions, type SyncOptions} from \"@jixo/dev/google-aistudio\";\nimport path from \"node:path\";\nimport type {Arguments, CommandModule} from \"yargs\";\n\n// 定义 yargs builder 所需的参数接口\ninterface SyncArgs {\n path?: string;\n watch?: boolean;\n outDir?: string;\n}\n\n// 定义 'sync' 子命令\nconst syncCommand: CommandModule<object, SyncArgs> = {\n command: \"sync [path]\",\n aliases: [\"S\", \"s\"],\n describe: \"Sync with aistudio.google.com contents\",\n builder: (yargs) =>\n yargs\n .positional(\"path\", {\n describe: \"Directory or file path to sync\",\n type: \"string\",\n default: process.cwd(),\n })\n .option(\"watch\", {\n alias: \"W\",\n type: \"boolean\",\n describe: \"Watch for file changes and sync automatically\",\n default: false,\n })\n .option(\"outDir\", {\n alias: \"O\",\n type: \"string\",\n describe: \"Specify the output directory for generated markdown files\",\n }),\n handler: async (argv: Arguments<SyncArgs>) => {\n // 将 yargs 的解析结果适配为 doSync 函数期望的格式。\n // 关键是 yargs 的位置参数是命名好的 (argv.path),而 doSync\n // 期望它在 `_` 数组的第一个位置。\n const optionsForDoSync: SyncOptions = {\n ...argv,\n _: [argv.path as string],\n };\n doSync(optionsForDoSync);\n },\n};\n\ninterface BrowserArgs {\n dir?: string;\n}\n\nconst browserCommand: CommandModule<object, BrowserArgs> = {\n command: \"browser [dir]\",\n aliases: [\"B\", \"b\"],\n describe: \"browser-kit for aistudio.google.com\",\n builder: (yargs) =>\n yargs.positional(\"dir\", {\n describe: \"Directory for aistudio output contents\",\n type: \"string\",\n default: process.cwd(),\n }),\n handler: async (argv) => {\n doGoogleAiStudioAutomation(argv.dir);\n },\n};\n\nconst initCommand: CommandModule<object, InitOptions> = {\n command: \"init [dir]\",\n aliases: [\"i\", \"I\"],\n describe: \"init an browser-kit directory for aistudio.google.com\",\n builder: (yargs) =>\n yargs\n .positional(\"dir\", {\n describe: \"Directory for aistudio input/output contents\",\n type: \"string\",\n default: path.resolve(process.cwd(), \".ai\"),\n })\n .option(\"force\", {\n alias: \"F\",\n type: \"boolean\",\n describe: \"override exits files\",\n }),\n handler: async (argv) => {\n doInit(argv);\n },\n};\n\n/**\n * @jixo/cli google-aistudio\n *\n * Group of commands for interacting with Google AI Studio.\n */\nexport const googleAistudioCommand: CommandModule<object, object> = {\n command: \"google-aistudio <command>\",\n aliases: [\"GO\", \"Go\", \"go\"],\n describe: \"Commands for Google AI Studio integration\",\n builder: (yargs) => {\n // 将 syncCommand 注册为 google-aistudio 的子命令\n return (\n yargs\n .command(syncCommand)\n .command(browserCommand)\n .command(initCommand)\n //\n .demandCommand(1, \"You must provide a sub-command for 'google-aistudio'.\")\n );\n },\n // 这个 handler 理论上不会被执行,因为 yargs 会要求一个子命令\n handler: () => {},\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export declare const init: (dir: string) => void;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,IAAI,GAAI,KAAK,MAAM,SA8B/B,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { 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
+ export const init = (dir) => {
6
+ // Create .jixo directory
7
+ const jixoDir = path.join(dir, ".jixo");
8
+ fs.mkdirSync(jixoDir, { recursive: true });
9
+ // Create .jixo.env file
10
+ const jixoEnvFilepath = path.join(dir, ".jixo.env");
11
+ if (!fs.existsSync(jixoEnvFilepath)) {
12
+ writeText(jixoEnvFilepath, str_trim_indent(`
13
+ # JIXO Core Service Configuration
14
+ JIXO_CORE_URL=http://localhost:4111
15
+ JIXO_API_KEY=
16
+
17
+ # LLM Provider API Keys (to be used by jixo-core)
18
+ # ANTHROPIC_API_KEY=
19
+ # GOOGLE_API_KEY=
20
+ # OPENAI_API_KEY=
21
+ `));
22
+ console.log(`✅ Created configuration template at: ${jixoEnvFilepath}`);
23
+ }
24
+ // Update root .gitignore
25
+ const gitignoreFilepath = path.join(dir, ".gitignore");
26
+ addRulesToGitIgnore(gitignoreFilepath, [".jixo.env", ".jixo/memory/"]);
27
+ console.log(`✅ Updated .gitignore`);
28
+ console.log("\nJIXO initialized successfully!");
29
+ };
30
+ const addRulesToGitIgnore = (gitignoreFilepath, rules) => {
31
+ const existingRules = fs.existsSync(gitignoreFilepath) ? fs.readFileSync(gitignoreFilepath, "utf-8").split("\n") : [];
32
+ let changed = false;
33
+ const newRules = rules.filter((rule) => !existingRules.includes(rule));
34
+ if (newRules.length > 0) {
35
+ fs.appendFileSync(gitignoreFilepath, "\n# JIXO\n" + newRules.join("\n") + "\n");
36
+ changed = true;
37
+ }
38
+ return changed;
39
+ };
40
+ //# sourceMappingURL=init.js.map