@bike4mind/cli 0.2.31-b4m-cli-undo-command.19493 → 0.2.31-b4m-cli-undo-command.19534
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/bin/bike4mind-cli.mjs +48 -0
- package/dist/{artifactExtractor-Z6CL6QFN.js → artifactExtractor-T6NJ7V7P.js} +1 -1
- package/dist/{chunk-LBTTUQJM.js → chunk-32PKF3N7.js} +16 -15
- package/dist/{chunk-RI45VJW3.js → chunk-3SPW5FYJ.js} +3 -3
- package/dist/{chunk-ZOWCX4MQ.js → chunk-ERV5G6MX.js} +3 -3
- package/dist/{chunk-2LLA4MTN.js → chunk-F4PXVLZX.js} +2 -2
- package/dist/{chunk-T67NGQW6.js → chunk-JWJF6O4L.js} +3 -3
- package/dist/{chunk-GE7Q64MS.js → chunk-NI22LIK3.js} +167 -165
- package/dist/{chunk-OCYRD7D6.js → chunk-PFBYGCOW.js} +109 -31
- package/dist/chunk-WVFOWKNW.js +244 -0
- package/dist/commands/doctorCommand.js +87 -0
- package/dist/commands/mcpCommand.js +1 -1
- package/dist/commands/updateCommand.js +42 -0
- package/dist/create-XOEMSBER.js +12 -0
- package/dist/index.js +161 -284
- package/dist/{llmMarkdownGenerator-KGA4HTQN.js → llmMarkdownGenerator-NPX7ULSW.js} +1 -1
- package/dist/{markdownGenerator-ERG7FI5H.js → markdownGenerator-TVJ2RQXC.js} +1 -1
- package/dist/{mementoService-I56R5DNA.js → mementoService-HGH2XVLM.js} +4 -4
- package/dist/{notificationDeduplicator-UTHJHMSZ.js → notificationDeduplicator-HUC53NEW.js} +1 -1
- package/dist/{src-IAR65K73.js → src-2BRBILH7.js} +1 -1
- package/dist/{src-EMANOLFK.js → src-JZ6OHGTX.js} +3 -3
- package/dist/{subtractCredits-3MEQF5CV.js → subtractCredits-4VIHTUR4.js} +4 -4
- package/package.json +9 -9
- package/dist/create-JNUW7ICC.js +0 -12
|
@@ -5,6 +5,7 @@ var Logger = class _Logger {
|
|
|
5
5
|
static globalInstance = new _Logger();
|
|
6
6
|
metadata = {};
|
|
7
7
|
logInJson;
|
|
8
|
+
prettyPrint;
|
|
8
9
|
minLevel;
|
|
9
10
|
// Log level hierarchy (higher number = more severe)
|
|
10
11
|
static LOG_LEVELS = {
|
|
@@ -13,15 +14,112 @@ var Logger = class _Logger {
|
|
|
13
14
|
warn: 2,
|
|
14
15
|
error: 3
|
|
15
16
|
};
|
|
17
|
+
// ANSI color codes for pretty printing
|
|
18
|
+
static COLORS = {
|
|
19
|
+
debug: "\x1B[36m",
|
|
20
|
+
// Cyan
|
|
21
|
+
info: "\x1B[32m",
|
|
22
|
+
// Green
|
|
23
|
+
warn: "\x1B[33m",
|
|
24
|
+
// Yellow
|
|
25
|
+
error: "\x1B[31m",
|
|
26
|
+
// Red
|
|
27
|
+
reset: "\x1B[0m",
|
|
28
|
+
dim: "\x1B[2m"
|
|
29
|
+
};
|
|
30
|
+
// Level labels for pretty printing (padded for alignment)
|
|
31
|
+
static LEVEL_LABELS = {
|
|
32
|
+
debug: "DEBUG",
|
|
33
|
+
info: " INFO",
|
|
34
|
+
warn: " WARN",
|
|
35
|
+
error: "ERROR"
|
|
36
|
+
};
|
|
37
|
+
// Indentation constants for pretty printing
|
|
38
|
+
static INDENT = " ";
|
|
39
|
+
static NESTED_INDENT = " ";
|
|
16
40
|
constructor(options = {}) {
|
|
17
|
-
const
|
|
41
|
+
const isLocalDev = process.env.IS_LOCAL === "true" || process.env.NODE_ENV === "development" || process.env.SST_LIVE === "true";
|
|
42
|
+
const { metadata = {}, logInJson = process.env.LOG_JSON === "true" || !isLocalDev, prettyPrint = isLocalDev && process.env.LOG_PRETTY !== "false", minLevel = process.env.LOG_LEVEL || "info" } = options;
|
|
18
43
|
this.metadata = metadata;
|
|
19
44
|
this.logInJson = logInJson;
|
|
45
|
+
this.prettyPrint = prettyPrint;
|
|
20
46
|
this.minLevel = minLevel;
|
|
21
47
|
}
|
|
22
48
|
shouldLog(level) {
|
|
23
49
|
return _Logger.LOG_LEVELS[level] >= _Logger.LOG_LEVELS[this.minLevel];
|
|
24
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Safely stringify a value, handling circular references
|
|
53
|
+
*/
|
|
54
|
+
safeStringify(value, indent) {
|
|
55
|
+
try {
|
|
56
|
+
return JSON.stringify(value, null, indent);
|
|
57
|
+
} catch {
|
|
58
|
+
return "[Circular]";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parse log arguments to extract message and optional metadata
|
|
63
|
+
*/
|
|
64
|
+
parseArgs(args, errorAware = false) {
|
|
65
|
+
if (args.length === 0) {
|
|
66
|
+
return { message: "" };
|
|
67
|
+
}
|
|
68
|
+
const lastArg = args[args.length - 1];
|
|
69
|
+
const hasMetadata = args.length > 1 && typeof lastArg === "object" && lastArg !== null && !Array.isArray(lastArg) && !(lastArg instanceof Error);
|
|
70
|
+
const metadata = hasMetadata ? lastArg : void 0;
|
|
71
|
+
const messageArgs = hasMetadata ? args.slice(0, -1) : args;
|
|
72
|
+
const message = messageArgs.map((a) => {
|
|
73
|
+
if (errorAware && a instanceof Error) {
|
|
74
|
+
return a.stack || a.message;
|
|
75
|
+
}
|
|
76
|
+
return typeof a === "string" ? a : this.safeStringify(a);
|
|
77
|
+
}).join(" ");
|
|
78
|
+
return { message, metadata };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Output a log message using the appropriate format
|
|
82
|
+
*/
|
|
83
|
+
output(level, consoleFn, message, metadata) {
|
|
84
|
+
const allMetadata = { ...this.metadata, ...metadata };
|
|
85
|
+
if (this.logInJson) {
|
|
86
|
+
consoleFn(this.safeStringify({ ...allMetadata, severity: level, message }));
|
|
87
|
+
} else if (this.prettyPrint) {
|
|
88
|
+
consoleFn(this.formatPretty(level, message, metadata));
|
|
89
|
+
} else {
|
|
90
|
+
const metadataKeys = Object.keys(allMetadata);
|
|
91
|
+
if (metadataKeys.length > 0) {
|
|
92
|
+
consoleFn(message, allMetadata);
|
|
93
|
+
} else {
|
|
94
|
+
consoleFn(message);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Format a log message with pino-pretty-like output for local development
|
|
100
|
+
*/
|
|
101
|
+
formatPretty(level, message, metadata) {
|
|
102
|
+
const { reset, dim } = _Logger.COLORS;
|
|
103
|
+
const color = _Logger.COLORS[level];
|
|
104
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
105
|
+
const parts = [];
|
|
106
|
+
parts.push(`${dim}[${timestamp}]${reset} ${color}${_Logger.LEVEL_LABELS[level]}${reset} ${message}`);
|
|
107
|
+
const allMetadata = { ...this.metadata, ...metadata };
|
|
108
|
+
const metadataKeys = Object.keys(allMetadata);
|
|
109
|
+
if (metadataKeys.length > 0) {
|
|
110
|
+
for (const key of metadataKeys) {
|
|
111
|
+
const value = allMetadata[key];
|
|
112
|
+
if (typeof value === "object" && value !== null) {
|
|
113
|
+
const jsonStr = this.safeStringify(value, 2);
|
|
114
|
+
const indentedJson = jsonStr.split("\n").map((line, idx) => idx === 0 ? line : _Logger.NESTED_INDENT + line).join("\n");
|
|
115
|
+
parts.push(`${_Logger.INDENT}${dim}${key}:${reset} ${indentedJson}`);
|
|
116
|
+
} else {
|
|
117
|
+
parts.push(`${_Logger.INDENT}${dim}${key}:${reset} ${value}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return parts.join("\n");
|
|
122
|
+
}
|
|
25
123
|
resetMetadata() {
|
|
26
124
|
this.metadata = {};
|
|
27
125
|
return this;
|
|
@@ -33,6 +131,7 @@ var Logger = class _Logger {
|
|
|
33
131
|
...metadata
|
|
34
132
|
},
|
|
35
133
|
logInJson: this.logInJson,
|
|
134
|
+
prettyPrint: this.prettyPrint,
|
|
36
135
|
minLevel: this.minLevel
|
|
37
136
|
});
|
|
38
137
|
}
|
|
@@ -49,47 +148,26 @@ var Logger = class _Logger {
|
|
|
49
148
|
debug(...args) {
|
|
50
149
|
if (!this.shouldLog("debug"))
|
|
51
150
|
return;
|
|
52
|
-
const message
|
|
53
|
-
|
|
54
|
-
console.debug(JSON.stringify({ ...this.metadata, severity: "debug", message }));
|
|
55
|
-
} else {
|
|
56
|
-
console.debug(message);
|
|
57
|
-
}
|
|
151
|
+
const { message, metadata } = this.parseArgs(args);
|
|
152
|
+
this.output("debug", console.debug, message, metadata);
|
|
58
153
|
}
|
|
59
154
|
info(...args) {
|
|
60
155
|
if (!this.shouldLog("info"))
|
|
61
156
|
return;
|
|
62
|
-
const message
|
|
63
|
-
|
|
64
|
-
console.info(JSON.stringify({ ...this.metadata, severity: "info", message }));
|
|
65
|
-
} else {
|
|
66
|
-
console.info(message);
|
|
67
|
-
}
|
|
157
|
+
const { message, metadata } = this.parseArgs(args);
|
|
158
|
+
this.output("info", console.info, message, metadata);
|
|
68
159
|
}
|
|
69
160
|
warn(...args) {
|
|
70
161
|
if (!this.shouldLog("warn"))
|
|
71
162
|
return;
|
|
72
|
-
const message
|
|
73
|
-
|
|
74
|
-
console.warn(JSON.stringify({ ...this.metadata, severity: "warn", message }));
|
|
75
|
-
} else {
|
|
76
|
-
console.warn(message);
|
|
77
|
-
}
|
|
163
|
+
const { message, metadata } = this.parseArgs(args);
|
|
164
|
+
this.output("warn", console.warn, message, metadata);
|
|
78
165
|
}
|
|
79
166
|
error(...args) {
|
|
80
167
|
if (!this.shouldLog("error"))
|
|
81
168
|
return;
|
|
82
|
-
const message =
|
|
83
|
-
|
|
84
|
-
return a.stack || a.message;
|
|
85
|
-
}
|
|
86
|
-
return typeof a === "string" ? a : JSON.stringify(a);
|
|
87
|
-
}).join(" ");
|
|
88
|
-
if (this.logInJson) {
|
|
89
|
-
console.error(JSON.stringify({ ...this.metadata, severity: "error", message }));
|
|
90
|
-
} else {
|
|
91
|
-
console.error(message);
|
|
92
|
-
}
|
|
169
|
+
const { message, metadata } = this.parseArgs(args, true);
|
|
170
|
+
this.output("error", console.error, message, metadata);
|
|
93
171
|
}
|
|
94
172
|
/*
|
|
95
173
|
* Global logger instance handling:
|
|
@@ -160,7 +238,7 @@ var notifyEventLogsToSlack = async ({ event, stage, slackUrl, throttlingSlackUrl
|
|
|
160
238
|
if (!allowedStages.includes(stage))
|
|
161
239
|
return;
|
|
162
240
|
const logEvents = logData.logEvents;
|
|
163
|
-
const { notificationDeduplicator: notificationDeduplicator2 } = await import("./notificationDeduplicator-
|
|
241
|
+
const { notificationDeduplicator: notificationDeduplicator2 } = await import("./notificationDeduplicator-HUC53NEW.js");
|
|
164
242
|
for (const logEvent of logEvents) {
|
|
165
243
|
try {
|
|
166
244
|
let message;
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// package.json
|
|
4
|
+
var package_default = {
|
|
5
|
+
name: "@bike4mind/cli",
|
|
6
|
+
version: "0.2.31-b4m-cli-undo-command.19534+db45140bb",
|
|
7
|
+
type: "module",
|
|
8
|
+
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
9
|
+
license: "UNLICENSED",
|
|
10
|
+
author: "Bike4Mind",
|
|
11
|
+
repository: {
|
|
12
|
+
type: "git",
|
|
13
|
+
url: "git+https://github.com/bike4mind/lumina5.git"
|
|
14
|
+
},
|
|
15
|
+
homepage: "https://github.com/bike4mind/lumina5#readme",
|
|
16
|
+
bugs: "https://github.com/bike4mind/lumina5/issues",
|
|
17
|
+
publishConfig: {
|
|
18
|
+
access: "public"
|
|
19
|
+
},
|
|
20
|
+
keywords: [
|
|
21
|
+
"cli",
|
|
22
|
+
"ai",
|
|
23
|
+
"bike4mind",
|
|
24
|
+
"agent",
|
|
25
|
+
"mcp",
|
|
26
|
+
"react-agent"
|
|
27
|
+
],
|
|
28
|
+
bin: {
|
|
29
|
+
b4m: "./bin/bike4mind-cli.mjs",
|
|
30
|
+
bike4mind: "./bin/bike4mind-cli.mjs"
|
|
31
|
+
},
|
|
32
|
+
files: [
|
|
33
|
+
"dist",
|
|
34
|
+
"bin"
|
|
35
|
+
],
|
|
36
|
+
scripts: {
|
|
37
|
+
dev: "tsx src/index.tsx",
|
|
38
|
+
build: "tsup",
|
|
39
|
+
typecheck: "tsc --noEmit",
|
|
40
|
+
test: "vitest run",
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
start: "node dist/index.js",
|
|
43
|
+
prepublishOnly: "pnpm build",
|
|
44
|
+
postinstall: `node -e "try { require('better-sqlite3') } catch(e) { if(e.message.includes('bindings')) { console.log('\\n\u26A0\uFE0F Rebuilding better-sqlite3 native bindings...'); require('child_process').execSync('pnpm rebuild better-sqlite3', {stdio:'inherit'}) } }"`
|
|
45
|
+
},
|
|
46
|
+
dependencies: {
|
|
47
|
+
"@anthropic-ai/sdk": "^0.71.2",
|
|
48
|
+
"@aws-sdk/client-apigatewaymanagementapi": "3.654.0",
|
|
49
|
+
"@aws-sdk/client-bedrock-runtime": "3.654.0",
|
|
50
|
+
"@aws-sdk/client-cloudwatch": "3.654.0",
|
|
51
|
+
"@aws-sdk/client-lambda": "3.654.0",
|
|
52
|
+
"@aws-sdk/client-s3": "3.654.0",
|
|
53
|
+
"@aws-sdk/client-sqs": "3.654.0",
|
|
54
|
+
"@aws-sdk/client-transcribe": "3.654.0",
|
|
55
|
+
"@aws-sdk/credential-provider-node": "3.654.0",
|
|
56
|
+
"@aws-sdk/node-http-handler": "^3.374.0",
|
|
57
|
+
"@aws-sdk/s3-request-presigner": "3.654.0",
|
|
58
|
+
"@casl/ability": "^6.5.0",
|
|
59
|
+
"@google/genai": "^1.27.0",
|
|
60
|
+
"@google/generative-ai": "^0.21.0",
|
|
61
|
+
"@joplin/turndown-plugin-gfm": "^1.0.62",
|
|
62
|
+
"@mendable/firecrawl-js": "^1.29.3",
|
|
63
|
+
"@modelcontextprotocol/sdk": "1.26.0",
|
|
64
|
+
"@octokit/rest": "^22.0.0",
|
|
65
|
+
"@opensearch-project/opensearch": "2.11.0",
|
|
66
|
+
"async-mutex": "^0.5.0",
|
|
67
|
+
axios: "^1.13.2",
|
|
68
|
+
bcryptjs: "^2.4.3",
|
|
69
|
+
"better-sqlite3": "^12.5.0",
|
|
70
|
+
cheerio: "1.0.0-rc.12",
|
|
71
|
+
"cli-highlight": "^2.1.11",
|
|
72
|
+
"csv-parse": "^5.5.6",
|
|
73
|
+
dayjs: "^1.11.13",
|
|
74
|
+
diff: "^8.0.2",
|
|
75
|
+
dotenv: "^16.3.1",
|
|
76
|
+
"eventsource-parser": "^3.0.6",
|
|
77
|
+
"file-type": "^18.7.0",
|
|
78
|
+
"fuse.js": "^7.1.0",
|
|
79
|
+
glob: "^13.0.0",
|
|
80
|
+
"gray-matter": "^4.0.3",
|
|
81
|
+
ink: "^6.5.1",
|
|
82
|
+
"ink-select-input": "^6.2.0",
|
|
83
|
+
"ink-spinner": "^5.0.0",
|
|
84
|
+
"ink-text-input": "^6.0.0",
|
|
85
|
+
jsonwebtoken: "^9.0.2",
|
|
86
|
+
lodash: "^4.17.21",
|
|
87
|
+
mammoth: "^1.11.0",
|
|
88
|
+
marked: "^15.0.11",
|
|
89
|
+
mathjs: "^14.2.0",
|
|
90
|
+
"mime-types": "^2.1.35",
|
|
91
|
+
mongoose: "^8.8.3",
|
|
92
|
+
ollama: "^0.5.12",
|
|
93
|
+
open: "^11.0.0",
|
|
94
|
+
openai: "^6.18.0",
|
|
95
|
+
"p-limit": "^6.2.0",
|
|
96
|
+
picomatch: "^4.0.3",
|
|
97
|
+
qrcode: "^1.5.4",
|
|
98
|
+
react: "^19.2.3",
|
|
99
|
+
sharp: "^0.34.5",
|
|
100
|
+
speakeasy: "^2.0.0",
|
|
101
|
+
tiktoken: "^1.0.16",
|
|
102
|
+
"tree-sitter-wasms": "^0.1.13",
|
|
103
|
+
turndown: "^7.2.0",
|
|
104
|
+
unpdf: "^0.10.0",
|
|
105
|
+
uuid: "^9.0.1",
|
|
106
|
+
voyageai: "^0.0.4",
|
|
107
|
+
"web-tree-sitter": "0.25.10",
|
|
108
|
+
xlsx: "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
|
|
109
|
+
yargs: "^17.7.2",
|
|
110
|
+
yauzl: "^3.1.3",
|
|
111
|
+
zod: "^4.3.6",
|
|
112
|
+
"zod-validation-error": "^5.0.0",
|
|
113
|
+
zustand: "^4.5.4"
|
|
114
|
+
},
|
|
115
|
+
devDependencies: {
|
|
116
|
+
"@bike4mind/agents": "0.1.0",
|
|
117
|
+
"@bike4mind/common": "2.52.1-b4m-cli-undo-command.19534+db45140bb",
|
|
118
|
+
"@bike4mind/mcp": "1.31.1-b4m-cli-undo-command.19534+db45140bb",
|
|
119
|
+
"@bike4mind/services": "2.50.1-b4m-cli-undo-command.19534+db45140bb",
|
|
120
|
+
"@bike4mind/utils": "2.7.1-b4m-cli-undo-command.19534+db45140bb",
|
|
121
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
122
|
+
"@types/diff": "^5.0.9",
|
|
123
|
+
"@types/jsonwebtoken": "^9.0.4",
|
|
124
|
+
"@types/node": "^22.9.0",
|
|
125
|
+
"@types/picomatch": "^4.0.2",
|
|
126
|
+
"@types/react": "^19.2.7",
|
|
127
|
+
"@types/uuid": "^9.0.7",
|
|
128
|
+
"@types/yargs": "^17.0.32",
|
|
129
|
+
fdir: "^6.5.0",
|
|
130
|
+
fzf: "^0.5.2",
|
|
131
|
+
ignore: "^7.0.5",
|
|
132
|
+
"ink-testing-library": "^4.0.0",
|
|
133
|
+
tsup: "^8.5.1",
|
|
134
|
+
tsx: "^4.21.0",
|
|
135
|
+
typescript: "^5.9.3",
|
|
136
|
+
vitest: "^3.2.4"
|
|
137
|
+
},
|
|
138
|
+
optionalDependencies: {
|
|
139
|
+
"@vscode/ripgrep": "^1.17.0"
|
|
140
|
+
},
|
|
141
|
+
gitHead: "db45140bb943bbc4dbccd53c99a8e305cb792d88"
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// src/utils/updateChecker.ts
|
|
145
|
+
import { promises as fs } from "fs";
|
|
146
|
+
import path from "path";
|
|
147
|
+
import { homedir } from "os";
|
|
148
|
+
import axios from "axios";
|
|
149
|
+
var CACHE_FILE = path.join(homedir(), ".bike4mind", "update-check.json");
|
|
150
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
151
|
+
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@bike4mind/cli/latest";
|
|
152
|
+
var FETCH_TIMEOUT_MS = 5e3;
|
|
153
|
+
function compareSemver(a, b) {
|
|
154
|
+
const partsA = a.split(".").map(Number);
|
|
155
|
+
const partsB = b.split(".").map(Number);
|
|
156
|
+
for (let i = 0; i < 3; i++) {
|
|
157
|
+
const segA = partsA[i] ?? 0;
|
|
158
|
+
const segB = partsB[i] ?? 0;
|
|
159
|
+
if (segA < segB) return -1;
|
|
160
|
+
if (segA > segB) return 1;
|
|
161
|
+
}
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
async function fetchLatestVersion() {
|
|
165
|
+
try {
|
|
166
|
+
const response = await axios.get(NPM_REGISTRY_URL, {
|
|
167
|
+
timeout: FETCH_TIMEOUT_MS,
|
|
168
|
+
headers: { Accept: "application/json" }
|
|
169
|
+
});
|
|
170
|
+
const version = response.data?.version;
|
|
171
|
+
return typeof version === "string" ? version : null;
|
|
172
|
+
} catch {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function readCache() {
|
|
177
|
+
try {
|
|
178
|
+
const data = await fs.readFile(CACHE_FILE, "utf-8");
|
|
179
|
+
const parsed = JSON.parse(data);
|
|
180
|
+
if (parsed && typeof parsed.lastChecked === "string" && typeof parsed.latestVersion === "string") {
|
|
181
|
+
return parsed;
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
} catch {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function writeCache(cache) {
|
|
189
|
+
try {
|
|
190
|
+
await fs.mkdir(path.dirname(CACHE_FILE), { recursive: true });
|
|
191
|
+
await fs.writeFile(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
|
|
192
|
+
} catch {
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async function checkForUpdate(currentVersion) {
|
|
196
|
+
try {
|
|
197
|
+
const cache = await readCache();
|
|
198
|
+
if (cache && cache.currentVersion === currentVersion) {
|
|
199
|
+
const age = Date.now() - new Date(cache.lastChecked).getTime();
|
|
200
|
+
if (age < CACHE_TTL_MS) {
|
|
201
|
+
return {
|
|
202
|
+
currentVersion,
|
|
203
|
+
latestVersion: cache.latestVersion,
|
|
204
|
+
updateAvailable: compareSemver(cache.latestVersion, currentVersion) > 0
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const latestVersion = await fetchLatestVersion();
|
|
209
|
+
if (!latestVersion) return null;
|
|
210
|
+
await writeCache({
|
|
211
|
+
lastChecked: (/* @__PURE__ */ new Date()).toISOString(),
|
|
212
|
+
latestVersion,
|
|
213
|
+
currentVersion
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
currentVersion,
|
|
217
|
+
latestVersion,
|
|
218
|
+
updateAvailable: compareSemver(latestVersion, currentVersion) > 0
|
|
219
|
+
};
|
|
220
|
+
} catch {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async function forceCheckForUpdate(currentVersion) {
|
|
225
|
+
const latestVersion = await fetchLatestVersion();
|
|
226
|
+
if (!latestVersion) return null;
|
|
227
|
+
await writeCache({
|
|
228
|
+
lastChecked: (/* @__PURE__ */ new Date()).toISOString(),
|
|
229
|
+
latestVersion,
|
|
230
|
+
currentVersion
|
|
231
|
+
});
|
|
232
|
+
return {
|
|
233
|
+
currentVersion,
|
|
234
|
+
latestVersion,
|
|
235
|
+
updateAvailable: compareSemver(latestVersion, currentVersion) > 0
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export {
|
|
240
|
+
package_default,
|
|
241
|
+
fetchLatestVersion,
|
|
242
|
+
checkForUpdate,
|
|
243
|
+
forceCheckForUpdate
|
|
244
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
fetchLatestVersion,
|
|
4
|
+
forceCheckForUpdate,
|
|
5
|
+
package_default
|
|
6
|
+
} from "../chunk-WVFOWKNW.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/doctorCommand.ts
|
|
9
|
+
import { execSync } from "child_process";
|
|
10
|
+
import { existsSync, constants } from "fs";
|
|
11
|
+
import { promises as fsPromises } from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import { homedir } from "os";
|
|
14
|
+
async function handleDoctorCommand() {
|
|
15
|
+
console.log("B4M CLI Doctor\n");
|
|
16
|
+
console.log("Running diagnostics...\n");
|
|
17
|
+
const results = [];
|
|
18
|
+
const nodeVersion = process.version;
|
|
19
|
+
const nodeMajor = parseInt(nodeVersion.slice(1).split(".")[0], 10);
|
|
20
|
+
if (nodeMajor >= 18) {
|
|
21
|
+
results.push({ name: "Node.js version", status: "pass", message: `${nodeVersion} (>= 18 required)` });
|
|
22
|
+
} else {
|
|
23
|
+
results.push({
|
|
24
|
+
name: "Node.js version",
|
|
25
|
+
status: "fail",
|
|
26
|
+
message: `${nodeVersion} (>= 18 required, please upgrade)`
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const latestVersion = await fetchLatestVersion();
|
|
30
|
+
if (latestVersion) {
|
|
31
|
+
results.push({ name: "NPM registry", status: "pass", message: `Accessible (latest: v${latestVersion})` });
|
|
32
|
+
} else {
|
|
33
|
+
results.push({ name: "NPM registry", status: "fail", message: "Not accessible \u2014 check your internet connection" });
|
|
34
|
+
}
|
|
35
|
+
const currentVersion = package_default.version;
|
|
36
|
+
const updateResult = await forceCheckForUpdate(currentVersion);
|
|
37
|
+
if (updateResult) {
|
|
38
|
+
if (updateResult.updateAvailable) {
|
|
39
|
+
results.push({
|
|
40
|
+
name: "Version",
|
|
41
|
+
status: "warn",
|
|
42
|
+
message: `v${currentVersion} installed, v${updateResult.latestVersion} available. Run: b4m update`
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
results.push({ name: "Version", status: "pass", message: `v${currentVersion} (latest)` });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const npmPrefix = execSync("npm config get prefix", { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
50
|
+
try {
|
|
51
|
+
await fsPromises.access(npmPrefix, constants.W_OK);
|
|
52
|
+
results.push({ name: "Global npm path", status: "pass", message: `${npmPrefix} (writable)` });
|
|
53
|
+
} catch {
|
|
54
|
+
results.push({
|
|
55
|
+
name: "Global npm path",
|
|
56
|
+
status: "warn",
|
|
57
|
+
message: `${npmPrefix} (not writable \u2014 may need sudo for updates)`
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
results.push({ name: "Global npm path", status: "warn", message: "Could not determine npm prefix" });
|
|
62
|
+
}
|
|
63
|
+
const configFile = path.join(homedir(), ".bike4mind", "config.json");
|
|
64
|
+
if (existsSync(configFile)) {
|
|
65
|
+
results.push({ name: "Config file", status: "pass", message: configFile });
|
|
66
|
+
} else {
|
|
67
|
+
results.push({ name: "Config file", status: "warn", message: `Not found at ${configFile}` });
|
|
68
|
+
}
|
|
69
|
+
console.log("Results:\n");
|
|
70
|
+
for (const result of results) {
|
|
71
|
+
const icon = result.status === "pass" ? "\x1B[32m\u2713\x1B[0m" : result.status === "warn" ? "\x1B[33m!\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
|
|
72
|
+
console.log(` ${icon} ${result.name}: ${result.message}`);
|
|
73
|
+
}
|
|
74
|
+
const failures = results.filter((r) => r.status === "fail");
|
|
75
|
+
const warnings = results.filter((r) => r.status === "warn");
|
|
76
|
+
console.log("");
|
|
77
|
+
if (failures.length > 0) {
|
|
78
|
+
console.log(`${failures.length} issue(s) found.`);
|
|
79
|
+
} else if (warnings.length > 0) {
|
|
80
|
+
console.log(`All checks passed with ${warnings.length} warning(s).`);
|
|
81
|
+
} else {
|
|
82
|
+
console.log("All checks passed.");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
handleDoctorCommand
|
|
87
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
forceCheckForUpdate,
|
|
4
|
+
package_default
|
|
5
|
+
} from "../chunk-WVFOWKNW.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/updateCommand.ts
|
|
8
|
+
import { execSync } from "child_process";
|
|
9
|
+
async function handleUpdateCommand() {
|
|
10
|
+
const currentVersion = package_default.version;
|
|
11
|
+
console.log(`Current version: v${currentVersion}`);
|
|
12
|
+
console.log("Checking for updates...\n");
|
|
13
|
+
const result = await forceCheckForUpdate(currentVersion);
|
|
14
|
+
if (!result) {
|
|
15
|
+
console.error("Failed to check for updates. Check your internet connection.");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
if (!result.updateAvailable) {
|
|
19
|
+
console.log(`Already on the latest version (v${currentVersion}).`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
console.log(`Update available: v${currentVersion} \u2192 v${result.latestVersion}
|
|
23
|
+
`);
|
|
24
|
+
console.log("Installing update...\n");
|
|
25
|
+
try {
|
|
26
|
+
execSync("npm install -g @bike4mind/cli@latest", {
|
|
27
|
+
stdio: "inherit",
|
|
28
|
+
timeout: 12e4
|
|
29
|
+
});
|
|
30
|
+
console.log(`
|
|
31
|
+
Successfully updated to v${result.latestVersion}.`);
|
|
32
|
+
} catch {
|
|
33
|
+
console.error("\nUpdate failed. Try running manually:");
|
|
34
|
+
console.error(" npm install -g @bike4mind/cli@latest");
|
|
35
|
+
console.error("\nIf you get permission errors, try:");
|
|
36
|
+
console.error(" sudo npm install -g @bike4mind/cli@latest");
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
handleUpdateCommand
|
|
42
|
+
};
|