@deepstorm/cli 0.2.2 → 0.2.3
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.js +374 -137
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1187,13 +1187,13 @@ var require_ast = __commonJS({
|
|
|
1187
1187
|
helperExpression: function helperExpression(node) {
|
|
1188
1188
|
return node.type === "SubExpression" || (node.type === "MustacheStatement" || node.type === "BlockStatement") && !!(node.params && node.params.length || node.hash);
|
|
1189
1189
|
},
|
|
1190
|
-
scopedId: function scopedId(
|
|
1191
|
-
return /^\.|this\b/.test(
|
|
1190
|
+
scopedId: function scopedId(path23) {
|
|
1191
|
+
return /^\.|this\b/.test(path23.original);
|
|
1192
1192
|
},
|
|
1193
1193
|
// an ID is simple if it only has one part, and that part is not
|
|
1194
1194
|
// `..` or `this`.
|
|
1195
|
-
simpleId: function simpleId(
|
|
1196
|
-
return
|
|
1195
|
+
simpleId: function simpleId(path23) {
|
|
1196
|
+
return path23.parts.length === 1 && !AST.helpers.scopedId(path23) && !path23.depth;
|
|
1197
1197
|
}
|
|
1198
1198
|
}
|
|
1199
1199
|
};
|
|
@@ -2263,12 +2263,12 @@ var require_helpers2 = __commonJS({
|
|
|
2263
2263
|
loc
|
|
2264
2264
|
};
|
|
2265
2265
|
}
|
|
2266
|
-
function prepareMustache(
|
|
2266
|
+
function prepareMustache(path23, params, hash, open, strip, locInfo) {
|
|
2267
2267
|
var escapeFlag = open.charAt(3) || open.charAt(2), escaped = escapeFlag !== "{" && escapeFlag !== "&";
|
|
2268
2268
|
var decorator = /\*/.test(open);
|
|
2269
2269
|
return {
|
|
2270
2270
|
type: decorator ? "Decorator" : "MustacheStatement",
|
|
2271
|
-
path:
|
|
2271
|
+
path: path23,
|
|
2272
2272
|
params,
|
|
2273
2273
|
hash,
|
|
2274
2274
|
escaped,
|
|
@@ -2586,9 +2586,9 @@ var require_compiler = __commonJS({
|
|
|
2586
2586
|
},
|
|
2587
2587
|
DecoratorBlock: function DecoratorBlock(decorator) {
|
|
2588
2588
|
var program2 = decorator.program && this.compileProgram(decorator.program);
|
|
2589
|
-
var params = this.setupFullMustacheParams(decorator, program2, void 0),
|
|
2589
|
+
var params = this.setupFullMustacheParams(decorator, program2, void 0), path23 = decorator.path;
|
|
2590
2590
|
this.useDecorators = true;
|
|
2591
|
-
this.opcode("registerDecorator", params.length,
|
|
2591
|
+
this.opcode("registerDecorator", params.length, path23.original);
|
|
2592
2592
|
},
|
|
2593
2593
|
PartialStatement: function PartialStatement(partial) {
|
|
2594
2594
|
this.usePartial = true;
|
|
@@ -2652,46 +2652,46 @@ var require_compiler = __commonJS({
|
|
|
2652
2652
|
}
|
|
2653
2653
|
},
|
|
2654
2654
|
ambiguousSexpr: function ambiguousSexpr(sexpr, program2, inverse) {
|
|
2655
|
-
var
|
|
2656
|
-
this.opcode("getContext",
|
|
2655
|
+
var path23 = sexpr.path, name = path23.parts[0], isBlock = program2 != null || inverse != null;
|
|
2656
|
+
this.opcode("getContext", path23.depth);
|
|
2657
2657
|
this.opcode("pushProgram", program2);
|
|
2658
2658
|
this.opcode("pushProgram", inverse);
|
|
2659
|
-
|
|
2660
|
-
this.accept(
|
|
2659
|
+
path23.strict = true;
|
|
2660
|
+
this.accept(path23);
|
|
2661
2661
|
this.opcode("invokeAmbiguous", name, isBlock);
|
|
2662
2662
|
},
|
|
2663
2663
|
simpleSexpr: function simpleSexpr(sexpr) {
|
|
2664
|
-
var
|
|
2665
|
-
|
|
2666
|
-
this.accept(
|
|
2664
|
+
var path23 = sexpr.path;
|
|
2665
|
+
path23.strict = true;
|
|
2666
|
+
this.accept(path23);
|
|
2667
2667
|
this.opcode("resolvePossibleLambda");
|
|
2668
2668
|
},
|
|
2669
2669
|
helperSexpr: function helperSexpr(sexpr, program2, inverse) {
|
|
2670
|
-
var params = this.setupFullMustacheParams(sexpr, program2, inverse),
|
|
2670
|
+
var params = this.setupFullMustacheParams(sexpr, program2, inverse), path23 = sexpr.path, name = path23.parts[0];
|
|
2671
2671
|
if (this.options.knownHelpers[name]) {
|
|
2672
2672
|
this.opcode("invokeKnownHelper", params.length, name);
|
|
2673
2673
|
} else if (this.options.knownHelpersOnly) {
|
|
2674
2674
|
throw new _exception2["default"]("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
|
|
2675
2675
|
} else {
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
this.accept(
|
|
2679
|
-
this.opcode("invokeHelper", params.length,
|
|
2676
|
+
path23.strict = true;
|
|
2677
|
+
path23.falsy = true;
|
|
2678
|
+
this.accept(path23);
|
|
2679
|
+
this.opcode("invokeHelper", params.length, path23.original, _ast2["default"].helpers.simpleId(path23));
|
|
2680
2680
|
}
|
|
2681
2681
|
},
|
|
2682
|
-
PathExpression: function PathExpression(
|
|
2683
|
-
this.addDepth(
|
|
2684
|
-
this.opcode("getContext",
|
|
2685
|
-
var name =
|
|
2682
|
+
PathExpression: function PathExpression(path23) {
|
|
2683
|
+
this.addDepth(path23.depth);
|
|
2684
|
+
this.opcode("getContext", path23.depth);
|
|
2685
|
+
var name = path23.parts[0], scoped = _ast2["default"].helpers.scopedId(path23), blockParamId = !path23.depth && !scoped && this.blockParamIndex(name);
|
|
2686
2686
|
if (blockParamId) {
|
|
2687
|
-
this.opcode("lookupBlockParam", blockParamId,
|
|
2687
|
+
this.opcode("lookupBlockParam", blockParamId, path23.parts);
|
|
2688
2688
|
} else if (!name) {
|
|
2689
2689
|
this.opcode("pushContext");
|
|
2690
|
-
} else if (
|
|
2690
|
+
} else if (path23.data) {
|
|
2691
2691
|
this.options.data = true;
|
|
2692
|
-
this.opcode("lookupData",
|
|
2692
|
+
this.opcode("lookupData", path23.depth, path23.parts, path23.strict);
|
|
2693
2693
|
} else {
|
|
2694
|
-
this.opcode("lookupOnContext",
|
|
2694
|
+
this.opcode("lookupOnContext", path23.parts, path23.falsy, path23.strict, scoped);
|
|
2695
2695
|
}
|
|
2696
2696
|
},
|
|
2697
2697
|
StringLiteral: function StringLiteral(string) {
|
|
@@ -3041,16 +3041,16 @@ var require_util = __commonJS({
|
|
|
3041
3041
|
}
|
|
3042
3042
|
exports2.urlGenerate = urlGenerate;
|
|
3043
3043
|
function normalize(aPath) {
|
|
3044
|
-
var
|
|
3044
|
+
var path23 = aPath;
|
|
3045
3045
|
var url = urlParse(aPath);
|
|
3046
3046
|
if (url) {
|
|
3047
3047
|
if (!url.path) {
|
|
3048
3048
|
return aPath;
|
|
3049
3049
|
}
|
|
3050
|
-
|
|
3050
|
+
path23 = url.path;
|
|
3051
3051
|
}
|
|
3052
|
-
var isAbsolute = exports2.isAbsolute(
|
|
3053
|
-
var parts =
|
|
3052
|
+
var isAbsolute = exports2.isAbsolute(path23);
|
|
3053
|
+
var parts = path23.split(/\/+/);
|
|
3054
3054
|
for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
|
|
3055
3055
|
part = parts[i];
|
|
3056
3056
|
if (part === ".") {
|
|
@@ -3067,18 +3067,18 @@ var require_util = __commonJS({
|
|
|
3067
3067
|
}
|
|
3068
3068
|
}
|
|
3069
3069
|
}
|
|
3070
|
-
|
|
3071
|
-
if (
|
|
3072
|
-
|
|
3070
|
+
path23 = parts.join("/");
|
|
3071
|
+
if (path23 === "") {
|
|
3072
|
+
path23 = isAbsolute ? "/" : ".";
|
|
3073
3073
|
}
|
|
3074
3074
|
if (url) {
|
|
3075
|
-
url.path =
|
|
3075
|
+
url.path = path23;
|
|
3076
3076
|
return urlGenerate(url);
|
|
3077
3077
|
}
|
|
3078
|
-
return
|
|
3078
|
+
return path23;
|
|
3079
3079
|
}
|
|
3080
3080
|
exports2.normalize = normalize;
|
|
3081
|
-
function
|
|
3081
|
+
function join21(aRoot, aPath) {
|
|
3082
3082
|
if (aRoot === "") {
|
|
3083
3083
|
aRoot = ".";
|
|
3084
3084
|
}
|
|
@@ -3110,11 +3110,11 @@ var require_util = __commonJS({
|
|
|
3110
3110
|
}
|
|
3111
3111
|
return joined;
|
|
3112
3112
|
}
|
|
3113
|
-
exports2.join =
|
|
3113
|
+
exports2.join = join21;
|
|
3114
3114
|
exports2.isAbsolute = function(aPath) {
|
|
3115
3115
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
3116
3116
|
};
|
|
3117
|
-
function
|
|
3117
|
+
function relative2(aRoot, aPath) {
|
|
3118
3118
|
if (aRoot === "") {
|
|
3119
3119
|
aRoot = ".";
|
|
3120
3120
|
}
|
|
@@ -3133,7 +3133,7 @@ var require_util = __commonJS({
|
|
|
3133
3133
|
}
|
|
3134
3134
|
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
|
|
3135
3135
|
}
|
|
3136
|
-
exports2.relative =
|
|
3136
|
+
exports2.relative = relative2;
|
|
3137
3137
|
var supportsNullProto = (function() {
|
|
3138
3138
|
var obj = /* @__PURE__ */ Object.create(null);
|
|
3139
3139
|
return !("__proto__" in obj);
|
|
@@ -3283,7 +3283,7 @@ var require_util = __commonJS({
|
|
|
3283
3283
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
3284
3284
|
}
|
|
3285
3285
|
}
|
|
3286
|
-
sourceURL =
|
|
3286
|
+
sourceURL = join21(urlGenerate(parsed), sourceURL);
|
|
3287
3287
|
}
|
|
3288
3288
|
return normalize(sourceURL);
|
|
3289
3289
|
}
|
|
@@ -5858,8 +5858,8 @@ var require_printer = __commonJS({
|
|
|
5858
5858
|
return this.accept(sexpr.path) + " " + params + hash;
|
|
5859
5859
|
};
|
|
5860
5860
|
PrintVisitor.prototype.PathExpression = function(id) {
|
|
5861
|
-
var
|
|
5862
|
-
return (id.data ? "@" : "") + "PATH:" +
|
|
5861
|
+
var path23 = id.parts.join("/");
|
|
5862
|
+
return (id.data ? "@" : "") + "PATH:" + path23;
|
|
5863
5863
|
};
|
|
5864
5864
|
PrintVisitor.prototype.StringLiteral = function(string) {
|
|
5865
5865
|
return '"' + string.value + '"';
|
|
@@ -5898,8 +5898,8 @@ var require_lib = __commonJS({
|
|
|
5898
5898
|
handlebars.print = printer.print;
|
|
5899
5899
|
module2.exports = handlebars;
|
|
5900
5900
|
function extension(module3, filename) {
|
|
5901
|
-
var
|
|
5902
|
-
var templateString =
|
|
5901
|
+
var fs25 = require("fs");
|
|
5902
|
+
var templateString = fs25.readFileSync(filename, "utf8");
|
|
5903
5903
|
module3.exports = handlebars.compile(templateString);
|
|
5904
5904
|
}
|
|
5905
5905
|
if (typeof require !== "undefined" && require.extensions) {
|
|
@@ -5911,8 +5911,8 @@ var require_lib = __commonJS({
|
|
|
5911
5911
|
|
|
5912
5912
|
// src/index.ts
|
|
5913
5913
|
var import_commander = require("commander");
|
|
5914
|
-
var
|
|
5915
|
-
var
|
|
5914
|
+
var fs24 = __toESM(require("node:fs"));
|
|
5915
|
+
var path22 = __toESM(require("node:path"));
|
|
5916
5916
|
|
|
5917
5917
|
// src/commands/setup.ts
|
|
5918
5918
|
var path6 = __toESM(require("node:path"));
|
|
@@ -8117,6 +8117,8 @@ function registerTemplateCommand(program2, registry2) {
|
|
|
8117
8117
|
}
|
|
8118
8118
|
|
|
8119
8119
|
// src/commands/update.ts
|
|
8120
|
+
var fs21 = __toESM(require("node:fs"));
|
|
8121
|
+
var path19 = __toESM(require("node:path"));
|
|
8120
8122
|
var import_node_child_process = require("node:child_process");
|
|
8121
8123
|
|
|
8122
8124
|
// src/utils/version.ts
|
|
@@ -8143,20 +8145,281 @@ function getCliVersion() {
|
|
|
8143
8145
|
// src/commands/template-upgrade.ts
|
|
8144
8146
|
var fs20 = __toESM(require("node:fs"));
|
|
8145
8147
|
var path18 = __toESM(require("node:path"));
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
+
var crypto = __toESM(require("node:crypto"));
|
|
8149
|
+
var CHECKSUM_FILE = "deepstorm-checksums.json";
|
|
8150
|
+
function computeFileChecksum(filePath) {
|
|
8151
|
+
try {
|
|
8152
|
+
if (!fs20.existsSync(filePath)) return null;
|
|
8153
|
+
const content = fs20.readFileSync(filePath);
|
|
8154
|
+
return crypto.createHash("sha256").update(content).digest("hex");
|
|
8155
|
+
} catch {
|
|
8156
|
+
return null;
|
|
8157
|
+
}
|
|
8158
|
+
}
|
|
8159
|
+
function computeDirChecksums(dirPath, relativeTo = dirPath) {
|
|
8160
|
+
const result = {};
|
|
8161
|
+
if (!fs20.existsSync(dirPath)) return result;
|
|
8162
|
+
function walk(current) {
|
|
8163
|
+
for (const entry of fs20.readdirSync(current, { withFileTypes: true })) {
|
|
8164
|
+
const fullPath = path18.join(current, entry.name);
|
|
8165
|
+
if (entry.name === ".DS_Store") continue;
|
|
8166
|
+
if (entry.isDirectory()) {
|
|
8167
|
+
walk(fullPath);
|
|
8168
|
+
} else if (entry.isFile()) {
|
|
8169
|
+
const relPath = path18.relative(relativeTo, fullPath);
|
|
8170
|
+
const checksum = computeFileChecksum(fullPath);
|
|
8171
|
+
if (checksum) result[relPath] = checksum;
|
|
8172
|
+
}
|
|
8173
|
+
}
|
|
8174
|
+
}
|
|
8175
|
+
walk(dirPath);
|
|
8176
|
+
return result;
|
|
8177
|
+
}
|
|
8178
|
+
function loadChecksums(targetDir) {
|
|
8179
|
+
const filePath = path18.join(targetDir, ".claude", CHECKSUM_FILE);
|
|
8180
|
+
try {
|
|
8181
|
+
return JSON.parse(fs20.readFileSync(filePath, "utf-8"));
|
|
8182
|
+
} catch {
|
|
8183
|
+
return {};
|
|
8184
|
+
}
|
|
8185
|
+
}
|
|
8186
|
+
function saveChecksums(targetDir, checksums) {
|
|
8187
|
+
const dir = path18.join(targetDir, ".claude");
|
|
8188
|
+
ensureDir(dir);
|
|
8189
|
+
fs20.writeFileSync(
|
|
8190
|
+
path18.join(dir, CHECKSUM_FILE),
|
|
8191
|
+
JSON.stringify(checksums, null, 2) + "\n",
|
|
8192
|
+
"utf-8"
|
|
8193
|
+
);
|
|
8194
|
+
}
|
|
8195
|
+
function backupFile(filePath) {
|
|
8196
|
+
try {
|
|
8197
|
+
if (!fs20.existsSync(filePath)) return null;
|
|
8198
|
+
const dir = path18.dirname(filePath);
|
|
8199
|
+
const ext = path18.extname(filePath);
|
|
8200
|
+
const base = path18.basename(filePath, ext);
|
|
8201
|
+
const timestamp = Date.now();
|
|
8202
|
+
const bakName = `${base}.${timestamp}.bak`;
|
|
8203
|
+
const bakPath = path18.join(dir, bakName);
|
|
8204
|
+
fs20.cpSync(filePath, bakPath, { force: true });
|
|
8205
|
+
return bakName;
|
|
8206
|
+
} catch {
|
|
8207
|
+
return null;
|
|
8208
|
+
}
|
|
8209
|
+
}
|
|
8210
|
+
function checkAndBackup(fileKey, filePath, stored, backedUp) {
|
|
8211
|
+
const lastChecksum = stored[fileKey];
|
|
8212
|
+
if (!lastChecksum) return;
|
|
8213
|
+
const current = computeFileChecksum(filePath);
|
|
8214
|
+
if (current === null) return;
|
|
8215
|
+
if (current === lastChecksum) return;
|
|
8216
|
+
const bakName = backupFile(filePath);
|
|
8217
|
+
if (bakName) {
|
|
8218
|
+
backedUp.push(`${fileKey} \u2192 ${bakName}`);
|
|
8219
|
+
}
|
|
8220
|
+
}
|
|
8221
|
+
function backupModifiedAssets(targetDir, skillIds, toolNames, registry2) {
|
|
8222
|
+
const stored = loadChecksums(targetDir);
|
|
8223
|
+
const backedUp = [];
|
|
8148
8224
|
for (const skillId of skillIds) {
|
|
8149
|
-
const
|
|
8150
|
-
if (fs20.existsSync(
|
|
8151
|
-
|
|
8225
|
+
const skillDir = path18.join(targetDir, ".claude", "skills", skillId);
|
|
8226
|
+
if (!fs20.existsSync(skillDir)) continue;
|
|
8227
|
+
const checksums = computeDirChecksums(skillDir);
|
|
8228
|
+
for (const [relPath] of Object.entries(checksums)) {
|
|
8229
|
+
const key = `skills/${skillId}/${relPath}`;
|
|
8230
|
+
checkAndBackup(key, path18.join(skillDir, relPath), stored, backedUp);
|
|
8231
|
+
}
|
|
8232
|
+
}
|
|
8233
|
+
const reader = new RegistryReader(registry2);
|
|
8234
|
+
for (const tool of toolNames) {
|
|
8235
|
+
const agents = reader.getToolAgents(tool);
|
|
8236
|
+
for (const agentFile of agents) {
|
|
8237
|
+
const filePath = path18.join(targetDir, ".claude", "agents", agentFile.replace(/\.tmpl$/, ""));
|
|
8238
|
+
const key = `agents/${agentFile.replace(/\.tmpl$/, "")}`;
|
|
8239
|
+
checkAndBackup(key, filePath, stored, backedUp);
|
|
8240
|
+
}
|
|
8241
|
+
}
|
|
8242
|
+
for (const tool of toolNames) {
|
|
8243
|
+
const hooks = reader.getToolHooks(tool);
|
|
8244
|
+
for (const hookFile of hooks) {
|
|
8245
|
+
const filePath = path18.join(targetDir, ".claude", "hooks", hookFile);
|
|
8246
|
+
const key = `hooks/${hookFile}`;
|
|
8247
|
+
checkAndBackup(key, filePath, stored, backedUp);
|
|
8248
|
+
}
|
|
8249
|
+
}
|
|
8250
|
+
return backedUp;
|
|
8251
|
+
}
|
|
8252
|
+
function storeNewChecksums(targetDir, skillIds, toolNames, registry2) {
|
|
8253
|
+
const newChecksums = {};
|
|
8254
|
+
const reader = new RegistryReader(registry2);
|
|
8255
|
+
for (const skillId of skillIds) {
|
|
8256
|
+
const skillDir = path18.join(targetDir, ".claude", "skills", skillId);
|
|
8257
|
+
const checksums = computeDirChecksums(skillDir);
|
|
8258
|
+
for (const [relPath, checksum] of Object.entries(checksums)) {
|
|
8259
|
+
newChecksums[`skills/${skillId}/${relPath}`] = checksum;
|
|
8260
|
+
}
|
|
8261
|
+
}
|
|
8262
|
+
for (const tool of toolNames) {
|
|
8263
|
+
const agents = reader.getToolAgents(tool);
|
|
8264
|
+
for (const agentFile of agents) {
|
|
8265
|
+
const installedName = agentFile.replace(/\.tmpl$/, "");
|
|
8266
|
+
const filePath = path18.join(targetDir, ".claude", "agents", installedName);
|
|
8267
|
+
const chk = computeFileChecksum(filePath);
|
|
8268
|
+
if (chk) newChecksums[`agents/${installedName}`] = chk;
|
|
8269
|
+
}
|
|
8270
|
+
}
|
|
8271
|
+
for (const tool of toolNames) {
|
|
8272
|
+
const hooks = reader.getToolHooks(tool);
|
|
8273
|
+
for (const hookFile of hooks) {
|
|
8274
|
+
const filePath = path18.join(targetDir, ".claude", "hooks", hookFile);
|
|
8275
|
+
const chk = computeFileChecksum(filePath);
|
|
8276
|
+
if (chk) newChecksums[`hooks/${hookFile}`] = chk;
|
|
8277
|
+
}
|
|
8278
|
+
}
|
|
8279
|
+
saveChecksums(targetDir, newChecksums);
|
|
8280
|
+
}
|
|
8281
|
+
function skillIdsToTools(skillIds, registry2) {
|
|
8282
|
+
const toolSet = /* @__PURE__ */ new Set();
|
|
8283
|
+
for (const skillId of skillIds) {
|
|
8284
|
+
const skill = registry2.skills[skillId];
|
|
8285
|
+
if (skill?.tool) {
|
|
8286
|
+
toolSet.add(skill.tool);
|
|
8287
|
+
}
|
|
8288
|
+
}
|
|
8289
|
+
return [...toolSet];
|
|
8290
|
+
}
|
|
8291
|
+
function readSettingsConfig(targetDir) {
|
|
8292
|
+
const settingsPath = path18.join(targetDir, ".claude", "settings.json");
|
|
8293
|
+
try {
|
|
8294
|
+
const raw = fs20.readFileSync(settingsPath, "utf-8");
|
|
8295
|
+
const settings = JSON.parse(raw);
|
|
8296
|
+
const deepstorm = settings.deepstorm || {};
|
|
8297
|
+
const metaKeys = /* @__PURE__ */ new Set([
|
|
8298
|
+
"installedSkills",
|
|
8299
|
+
"installedMcpServers",
|
|
8300
|
+
"installedAt",
|
|
8301
|
+
"mcpCapabilities"
|
|
8302
|
+
]);
|
|
8303
|
+
const config = {};
|
|
8304
|
+
flattenNestedConfig(deepstorm, "", config, metaKeys);
|
|
8305
|
+
const installedMcpTools = deepstorm.installedMcpServers ?? [];
|
|
8306
|
+
return { config, installedMcpTools };
|
|
8307
|
+
} catch {
|
|
8308
|
+
return { config: {}, installedMcpTools: [] };
|
|
8309
|
+
}
|
|
8310
|
+
}
|
|
8311
|
+
function flattenNestedConfig(obj, prefix, result, skipKeys) {
|
|
8312
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
8313
|
+
if (skipKeys.has(key)) continue;
|
|
8314
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
8315
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
8316
|
+
flattenNestedConfig(value, fullKey, result, skipKeys);
|
|
8317
|
+
} else if (typeof value === "string") {
|
|
8318
|
+
result[fullKey] = value;
|
|
8319
|
+
}
|
|
8320
|
+
}
|
|
8321
|
+
}
|
|
8322
|
+
function loadRegistryFromCliDir(cliDir2) {
|
|
8323
|
+
const registryPath = path18.join(cliDir2, "registry.json");
|
|
8324
|
+
try {
|
|
8325
|
+
const raw = fs20.readFileSync(registryPath, "utf-8");
|
|
8326
|
+
return JSON.parse(raw);
|
|
8327
|
+
} catch {
|
|
8328
|
+
return null;
|
|
8329
|
+
}
|
|
8330
|
+
}
|
|
8331
|
+
function mergeToolHooksJson(toolNames, cliDir2, targetDir) {
|
|
8332
|
+
const hooksSrcDir = path18.join(cliDir2, "hooks");
|
|
8333
|
+
const targetHooksDir = path18.join(targetDir, ".claude", "hooks");
|
|
8334
|
+
const destHooksJson = path18.join(targetHooksDir, "hooks.json");
|
|
8335
|
+
for (const tool of toolNames) {
|
|
8336
|
+
const toolHooksJsonPath = path18.join(hooksSrcDir, `${tool}-hooks.json`);
|
|
8337
|
+
if (fs20.existsSync(toolHooksJsonPath)) {
|
|
8338
|
+
ensureDir(targetHooksDir);
|
|
8339
|
+
const incoming = JSON.parse(fs20.readFileSync(toolHooksJsonPath, "utf-8"));
|
|
8340
|
+
mergeHooks(destHooksJson, incoming);
|
|
8341
|
+
}
|
|
8342
|
+
}
|
|
8343
|
+
}
|
|
8344
|
+
function syncToolAssets(cliDir2, targetDir, installedSkillIds) {
|
|
8345
|
+
const registry2 = loadRegistryFromCliDir(cliDir2);
|
|
8346
|
+
if (!registry2) {
|
|
8347
|
+
console.log("\u26A0 \u65E0\u6CD5\u52A0\u8F7D registry.json\uFF0C\u8DF3\u8FC7\u8D44\u4EA7\u540C\u6B65");
|
|
8348
|
+
return { syncedSkills: [], syncedAgents: [], syncedHooks: [], backedUpFiles: [] };
|
|
8349
|
+
}
|
|
8350
|
+
const reader = new RegistryReader(registry2);
|
|
8351
|
+
const toolNames = skillIdsToTools(installedSkillIds, registry2);
|
|
8352
|
+
if (toolNames.length === 0) {
|
|
8353
|
+
console.log("\u26A0 \u65E0\u6CD5\u4ECE\u5DF2\u5B89\u88C5 skill \u89E3\u6790\u5DE5\u5177\u540D\u79F0\uFF0C\u8DF3\u8FC7\u8D44\u4EA7\u540C\u6B65");
|
|
8354
|
+
return { syncedSkills: [], syncedAgents: [], syncedHooks: [], backedUpFiles: [] };
|
|
8355
|
+
}
|
|
8356
|
+
const { config, installedMcpTools } = readSettingsConfig(targetDir);
|
|
8357
|
+
const templateVariables = buildTemplateVariables(registry2, config, installedMcpTools);
|
|
8358
|
+
const backedUpFiles = backupModifiedAssets(targetDir, installedSkillIds, toolNames, registry2);
|
|
8359
|
+
if (backedUpFiles.length > 0) {
|
|
8360
|
+
console.log("\n\u26A0 \u68C0\u6D4B\u5230\u7528\u6237\u4FEE\u6539\u7684\u6587\u4EF6\uFF1A");
|
|
8361
|
+
for (const info of backedUpFiles) {
|
|
8362
|
+
console.log(` \u5DF2\u5907\u4EFD ${info}`);
|
|
8363
|
+
}
|
|
8364
|
+
console.log("");
|
|
8365
|
+
}
|
|
8366
|
+
const actualSkillIds = [];
|
|
8367
|
+
const syncedAgents = [];
|
|
8368
|
+
const syncedHooks = [];
|
|
8369
|
+
let hasWarning = false;
|
|
8370
|
+
for (const tool of toolNames) {
|
|
8371
|
+
try {
|
|
8372
|
+
reader.getToolEntry(tool);
|
|
8373
|
+
} catch {
|
|
8152
8374
|
continue;
|
|
8153
8375
|
}
|
|
8154
|
-
const
|
|
8155
|
-
const
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8376
|
+
const beforeAgents = reader.getToolAgents(tool);
|
|
8377
|
+
const beforeHooks = reader.getToolHooks(tool);
|
|
8378
|
+
try {
|
|
8379
|
+
const ids = renderToolAssets(
|
|
8380
|
+
tool,
|
|
8381
|
+
reader,
|
|
8382
|
+
cliDir2,
|
|
8383
|
+
targetDir,
|
|
8384
|
+
templateVariables,
|
|
8385
|
+
config,
|
|
8386
|
+
registry2,
|
|
8387
|
+
installedMcpTools,
|
|
8388
|
+
".claude"
|
|
8389
|
+
);
|
|
8390
|
+
actualSkillIds.push(...ids);
|
|
8391
|
+
syncedAgents.push(...beforeAgents);
|
|
8392
|
+
syncedHooks.push(...beforeHooks);
|
|
8393
|
+
} catch (err) {
|
|
8394
|
+
hasWarning = true;
|
|
8395
|
+
console.log(` \u26A0 ${tool} \u540C\u6B65\u51FA\u9519: ${err instanceof Error ? err.message : String(err)}`);
|
|
8396
|
+
}
|
|
8397
|
+
}
|
|
8398
|
+
const syncedSkills = actualSkillIds.length > 0 ? actualSkillIds : [...installedSkillIds];
|
|
8399
|
+
mergeToolHooksJson(toolNames, cliDir2, targetDir);
|
|
8400
|
+
storeNewChecksums(targetDir, installedSkillIds, toolNames, registry2);
|
|
8401
|
+
if (hasWarning) {
|
|
8402
|
+
console.log("\n\u26A0 \u90E8\u5206\u5DE5\u5177\u540C\u6B65\u51FA\u9519\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5");
|
|
8403
|
+
}
|
|
8404
|
+
const uniqueAgents = [...new Set(syncedAgents)];
|
|
8405
|
+
const uniqueHooks = [...new Set(syncedHooks)];
|
|
8406
|
+
return {
|
|
8407
|
+
syncedSkills,
|
|
8408
|
+
syncedAgents: uniqueAgents,
|
|
8409
|
+
syncedHooks: uniqueHooks,
|
|
8410
|
+
backedUpFiles
|
|
8411
|
+
};
|
|
8412
|
+
}
|
|
8413
|
+
function upgradeTemplates(cliDir2, targetDir, skillIds) {
|
|
8414
|
+
const report = syncToolAssets(cliDir2, targetDir, skillIds);
|
|
8415
|
+
if (report.syncedSkills.length > 0) {
|
|
8416
|
+
const count = report.syncedSkills.length;
|
|
8417
|
+
const agentCount = report.syncedAgents.length;
|
|
8418
|
+
const hookCount = report.syncedHooks.length;
|
|
8419
|
+
console.log(`
|
|
8420
|
+
\u2714 \u540C\u6B65\u5B8C\u6210\uFF1A${count} \u4E2A skill${agentCount > 0 ? `\u3001${agentCount} \u4E2A agent` : ""}${hookCount > 0 ? `\u3001${hookCount} \u4E2A hook` : ""}`);
|
|
8421
|
+
if (report.backedUpFiles.length > 0) {
|
|
8422
|
+
console.log(` \u5DF2\u5907\u4EFD ${report.backedUpFiles.length} \u4E2A\u4FEE\u6539\u8FC7\u7684\u6587\u4EF6`);
|
|
8160
8423
|
}
|
|
8161
8424
|
}
|
|
8162
8425
|
}
|
|
@@ -8227,62 +8490,36 @@ async function updateCLI(fetchFn) {
|
|
|
8227
8490
|
console.log("\u2713 \u5DF2\u662F\u6700\u65B0\u7248\u672C");
|
|
8228
8491
|
}
|
|
8229
8492
|
}
|
|
8230
|
-
function
|
|
8231
|
-
|
|
8493
|
+
function getInstalledSkillIds(targetDir) {
|
|
8494
|
+
const settingsPath = path19.join(targetDir, ".claude", "settings.json");
|
|
8495
|
+
try {
|
|
8496
|
+
const raw = fs21.readFileSync(settingsPath, "utf-8");
|
|
8497
|
+
const settings = JSON.parse(raw);
|
|
8498
|
+
return settings.deepstorm?.installedSkills ?? [];
|
|
8499
|
+
} catch {
|
|
8500
|
+
return [];
|
|
8501
|
+
}
|
|
8232
8502
|
}
|
|
8233
|
-
function registerUpdateCommand(program2
|
|
8503
|
+
function registerUpdateCommand(program2) {
|
|
8234
8504
|
const cliDir2 = __dirname;
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
console.log("");
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
}
|
|
8244
|
-
if (check) {
|
|
8245
|
-
const result = await checkNpmVersion();
|
|
8246
|
-
printVersionInfo(result);
|
|
8247
|
-
if (result.error) process.exit(1);
|
|
8248
|
-
return;
|
|
8249
|
-
}
|
|
8250
|
-
if (cli) {
|
|
8251
|
-
await updateCLI();
|
|
8252
|
-
return;
|
|
8253
|
-
}
|
|
8254
|
-
if (skills) {
|
|
8255
|
-
const skillIds = Object.keys(registry2.skills);
|
|
8256
|
-
if (skillIds.length === 0) {
|
|
8257
|
-
console.log("registry \u4E2D\u65E0\u5DF2\u6CE8\u518C skill");
|
|
8258
|
-
return;
|
|
8259
|
-
}
|
|
8260
|
-
updateSkills(cliDir2, process.cwd(), skillIds);
|
|
8261
|
-
return;
|
|
8505
|
+
program2.command("update").description("\u68C0\u67E5 CLI \u66F4\u65B0\u5E76\u540C\u6B65\u5DF2\u5B89\u88C5 skill \u7684\u5B98\u65B9\u6700\u65B0\u6A21\u677F").action(async () => {
|
|
8506
|
+
await updateCLI();
|
|
8507
|
+
console.log("");
|
|
8508
|
+
const installedIds = getInstalledSkillIds(process.cwd());
|
|
8509
|
+
if (installedIds.length === 0) {
|
|
8510
|
+
console.log("\u672A\u68C0\u6D4B\u5230\u5DF2\u5B89\u88C5\u7684 skill\uFF0C\u8DF3\u8FC7\u540C\u6B65");
|
|
8511
|
+
} else {
|
|
8512
|
+
upgradeTemplates(cliDir2, process.cwd(), installedIds);
|
|
8262
8513
|
}
|
|
8263
8514
|
});
|
|
8264
8515
|
}
|
|
8265
|
-
function printVersionInfo(result) {
|
|
8266
|
-
if (result.error) {
|
|
8267
|
-
console.log(`\u26A0 \u65E0\u6CD5\u68C0\u67E5\u66F4\u65B0\uFF1A${result.error}`);
|
|
8268
|
-
return;
|
|
8269
|
-
}
|
|
8270
|
-
console.log(`\u2714 \u5F53\u524D\u7248\u672C: v${result.current}`);
|
|
8271
|
-
console.log(`\u2714 \u6700\u65B0\u7248\u672C: v${result.latest}`);
|
|
8272
|
-
if (result.hasUpdate) {
|
|
8273
|
-
console.log("");
|
|
8274
|
-
console.log('\u2192 \u6709\u65B0\u7248\u672C\u53EF\u7528\uFF01\u8FD0\u884C "deepstorm update --cli" \u66F4\u65B0');
|
|
8275
|
-
} else {
|
|
8276
|
-
console.log("\u2713 \u5DF2\u662F\u6700\u65B0\u7248\u672C");
|
|
8277
|
-
}
|
|
8278
|
-
}
|
|
8279
8516
|
|
|
8280
8517
|
// src/commands/doctor.ts
|
|
8281
|
-
var
|
|
8282
|
-
var
|
|
8518
|
+
var fs22 = __toESM(require("node:fs"));
|
|
8519
|
+
var path20 = __toESM(require("node:path"));
|
|
8283
8520
|
function getInstalledSkills(settingsPath) {
|
|
8284
8521
|
try {
|
|
8285
|
-
const settings = JSON.parse(
|
|
8522
|
+
const settings = JSON.parse(fs22.readFileSync(settingsPath, "utf-8"));
|
|
8286
8523
|
return settings.deepstorm?.installedSkills || [];
|
|
8287
8524
|
} catch {
|
|
8288
8525
|
return [];
|
|
@@ -8291,7 +8528,7 @@ function getInstalledSkills(settingsPath) {
|
|
|
8291
8528
|
function runDoctor(targetDir) {
|
|
8292
8529
|
const checks = [];
|
|
8293
8530
|
const version = getCliVersion();
|
|
8294
|
-
const settingsPath =
|
|
8531
|
+
const settingsPath = path20.join(targetDir, ".claude", "settings.json");
|
|
8295
8532
|
readDeepStormConfig(settingsPath);
|
|
8296
8533
|
checks.push({
|
|
8297
8534
|
name: "CLI \u7248\u672C",
|
|
@@ -8299,7 +8536,7 @@ function runDoctor(targetDir) {
|
|
|
8299
8536
|
message: `v${version}\uFF08\u8FD0\u884C deepstorm update --check \u68C0\u67E5\u6700\u65B0\u7248\u672C\uFF09`
|
|
8300
8537
|
});
|
|
8301
8538
|
let hasDeepStorm = false;
|
|
8302
|
-
if (!
|
|
8539
|
+
if (!fs22.existsSync(settingsPath)) {
|
|
8303
8540
|
checks.push({
|
|
8304
8541
|
name: "\u914D\u7F6E\u6587\u4EF6",
|
|
8305
8542
|
status: "warn",
|
|
@@ -8307,7 +8544,7 @@ function runDoctor(targetDir) {
|
|
|
8307
8544
|
});
|
|
8308
8545
|
} else {
|
|
8309
8546
|
try {
|
|
8310
|
-
const settings = JSON.parse(
|
|
8547
|
+
const settings = JSON.parse(fs22.readFileSync(settingsPath, "utf-8"));
|
|
8311
8548
|
if (settings.deepstorm) {
|
|
8312
8549
|
hasDeepStorm = true;
|
|
8313
8550
|
checks.push({
|
|
@@ -8330,20 +8567,20 @@ function runDoctor(targetDir) {
|
|
|
8330
8567
|
});
|
|
8331
8568
|
}
|
|
8332
8569
|
}
|
|
8333
|
-
const skillsDir =
|
|
8334
|
-
if (
|
|
8335
|
-
const skillDirs =
|
|
8336
|
-
(n) =>
|
|
8570
|
+
const skillsDir = path20.join(targetDir, ".claude", "skills");
|
|
8571
|
+
if (fs22.existsSync(skillsDir)) {
|
|
8572
|
+
const skillDirs = fs22.readdirSync(skillsDir).filter(
|
|
8573
|
+
(n) => fs22.statSync(path20.join(skillsDir, n)).isDirectory()
|
|
8337
8574
|
);
|
|
8338
8575
|
let validCount = 0;
|
|
8339
8576
|
let invalidCount = 0;
|
|
8340
8577
|
for (const skillName of skillDirs) {
|
|
8341
|
-
const skillMd =
|
|
8342
|
-
if (!
|
|
8578
|
+
const skillMd = path20.join(skillsDir, skillName, "SKILL.md");
|
|
8579
|
+
if (!fs22.existsSync(skillMd)) {
|
|
8343
8580
|
invalidCount++;
|
|
8344
8581
|
continue;
|
|
8345
8582
|
}
|
|
8346
|
-
const content =
|
|
8583
|
+
const content = fs22.readFileSync(skillMd, "utf-8");
|
|
8347
8584
|
const frontmatter = parseFrontmatter(content);
|
|
8348
8585
|
if (frontmatter && frontmatter.name) {
|
|
8349
8586
|
validCount++;
|
|
@@ -8373,7 +8610,7 @@ function runDoctor(targetDir) {
|
|
|
8373
8610
|
const installedSkills = getInstalledSkills(settingsPath);
|
|
8374
8611
|
const missingSkills = [];
|
|
8375
8612
|
for (const skillId of installedSkills) {
|
|
8376
|
-
if (!
|
|
8613
|
+
if (!fs22.existsSync(path20.join(skillsDir, skillId))) {
|
|
8377
8614
|
missingSkills.push(skillId);
|
|
8378
8615
|
}
|
|
8379
8616
|
}
|
|
@@ -8397,10 +8634,10 @@ function runDoctor(targetDir) {
|
|
|
8397
8634
|
message: ".claude/skills/ \u4E0D\u5B58\u5728"
|
|
8398
8635
|
});
|
|
8399
8636
|
}
|
|
8400
|
-
const mcpPath =
|
|
8401
|
-
if (
|
|
8637
|
+
const mcpPath = path20.join(targetDir, ".mcp.json");
|
|
8638
|
+
if (fs22.existsSync(mcpPath)) {
|
|
8402
8639
|
try {
|
|
8403
|
-
const mcp = JSON.parse(
|
|
8640
|
+
const mcp = JSON.parse(fs22.readFileSync(mcpPath, "utf-8"));
|
|
8404
8641
|
const hasServers = mcp.mcpServers && Object.keys(mcp.mcpServers).length > 0;
|
|
8405
8642
|
checks.push({
|
|
8406
8643
|
name: "MCP \u670D\u52A1\u5668",
|
|
@@ -8421,12 +8658,12 @@ function runDoctor(targetDir) {
|
|
|
8421
8658
|
message: ".mcp.json \u4E0D\u5B58\u5728"
|
|
8422
8659
|
});
|
|
8423
8660
|
}
|
|
8424
|
-
if (hasDeepStorm &&
|
|
8661
|
+
if (hasDeepStorm && fs22.existsSync(settingsPath)) {
|
|
8425
8662
|
try {
|
|
8426
|
-
const settings = JSON.parse(
|
|
8663
|
+
const settings = JSON.parse(fs22.readFileSync(settingsPath, "utf-8"));
|
|
8427
8664
|
const installedMcp = settings.deepstorm?.installedMcpServers;
|
|
8428
8665
|
if (installedMcp && installedMcp.length > 0) {
|
|
8429
|
-
const mcpExists =
|
|
8666
|
+
const mcpExists = fs22.existsSync(mcpPath);
|
|
8430
8667
|
if (!mcpExists) {
|
|
8431
8668
|
checks.push({
|
|
8432
8669
|
name: "MCP \u4E00\u81F4\u6027",
|
|
@@ -8435,7 +8672,7 @@ function runDoctor(targetDir) {
|
|
|
8435
8672
|
});
|
|
8436
8673
|
} else {
|
|
8437
8674
|
try {
|
|
8438
|
-
const mcpConfig = JSON.parse(
|
|
8675
|
+
const mcpConfig = JSON.parse(fs22.readFileSync(mcpPath, "utf-8"));
|
|
8439
8676
|
const servers = mcpConfig.mcpServers || {};
|
|
8440
8677
|
const missing = [];
|
|
8441
8678
|
for (const toolName of installedMcp) {
|
|
@@ -8463,9 +8700,9 @@ function runDoctor(targetDir) {
|
|
|
8463
8700
|
} catch {
|
|
8464
8701
|
}
|
|
8465
8702
|
}
|
|
8466
|
-
if (hasDeepStorm &&
|
|
8703
|
+
if (hasDeepStorm && fs22.existsSync(settingsPath)) {
|
|
8467
8704
|
try {
|
|
8468
|
-
const settings = JSON.parse(
|
|
8705
|
+
const settings = JSON.parse(fs22.readFileSync(settingsPath, "utf-8"));
|
|
8469
8706
|
const config = settings.deepstorm;
|
|
8470
8707
|
const validKeys = loadValidConfigKeys();
|
|
8471
8708
|
if (validKeys.size > 0 && config) {
|
|
@@ -8519,18 +8756,18 @@ function printDoctorReport(report) {
|
|
|
8519
8756
|
}
|
|
8520
8757
|
|
|
8521
8758
|
// src/commands/uninstall.ts
|
|
8522
|
-
var
|
|
8523
|
-
var
|
|
8759
|
+
var fs23 = __toESM(require("node:fs"));
|
|
8760
|
+
var path21 = __toESM(require("node:path"));
|
|
8524
8761
|
var import_prompts4 = require("@clack/prompts");
|
|
8525
8762
|
async function uninstallDeepStorm(targetDir) {
|
|
8526
|
-
const settingsPath =
|
|
8527
|
-
if (!
|
|
8763
|
+
const settingsPath = path21.join(targetDir, ".claude", "settings.json");
|
|
8764
|
+
if (!fs23.existsSync(settingsPath)) {
|
|
8528
8765
|
console.log("DeepStorm \u5C1A\u672A\u914D\u7F6E\uFF0C\u65E0\u9700\u5378\u8F7D");
|
|
8529
8766
|
return;
|
|
8530
8767
|
}
|
|
8531
8768
|
let hasDeepStorm = false;
|
|
8532
8769
|
try {
|
|
8533
|
-
const settings = JSON.parse(
|
|
8770
|
+
const settings = JSON.parse(fs23.readFileSync(settingsPath, "utf-8"));
|
|
8534
8771
|
hasDeepStorm = !!settings.deepstorm;
|
|
8535
8772
|
} catch {
|
|
8536
8773
|
}
|
|
@@ -8540,14 +8777,14 @@ async function uninstallDeepStorm(targetDir) {
|
|
|
8540
8777
|
}
|
|
8541
8778
|
cleanInstalled(targetDir);
|
|
8542
8779
|
resetConfig(targetDir);
|
|
8543
|
-
const templatesDir =
|
|
8544
|
-
if (
|
|
8780
|
+
const templatesDir = path21.join(targetDir, ".deepstorm", "templates");
|
|
8781
|
+
if (fs23.existsSync(templatesDir)) {
|
|
8545
8782
|
const shouldDelete = await (0, import_prompts4.confirm)({
|
|
8546
8783
|
message: "\u662F\u5426\u5220\u9664 .deepstorm/templates/ \u76EE\u5F55\uFF1F",
|
|
8547
8784
|
initialValue: false
|
|
8548
8785
|
});
|
|
8549
8786
|
if (shouldDelete) {
|
|
8550
|
-
|
|
8787
|
+
fs23.rmSync(templatesDir, { recursive: true, force: true });
|
|
8551
8788
|
console.log("\u2714 .deepstorm/templates/ \u5DF2\u5220\u9664");
|
|
8552
8789
|
} else {
|
|
8553
8790
|
console.log("\u4FDD\u7559 .deepstorm/templates/");
|
|
@@ -8560,9 +8797,9 @@ async function uninstallDeepStorm(targetDir) {
|
|
|
8560
8797
|
var program = new import_commander.Command();
|
|
8561
8798
|
program.name("deepstorm").description("DeepStorm CLI \u2014 \u4E00\u952E\u914D\u7F6E\u9879\u76EE\u5F00\u53D1\u73AF\u5883").version(getCliVersion(), "-v, --version", "\u8F93\u51FA\u7248\u672C\u53F7");
|
|
8562
8799
|
function loadRegistry() {
|
|
8563
|
-
const registryPath =
|
|
8800
|
+
const registryPath = path22.join(__dirname, "registry.json");
|
|
8564
8801
|
try {
|
|
8565
|
-
const raw =
|
|
8802
|
+
const raw = fs24.readFileSync(registryPath, "utf-8");
|
|
8566
8803
|
return JSON.parse(raw);
|
|
8567
8804
|
} catch {
|
|
8568
8805
|
return { version: "1", tools: {}, wizards: {}, skills: {} };
|
|
@@ -8573,7 +8810,7 @@ registerSetupCommand(program, registry);
|
|
|
8573
8810
|
registerPluginBuildCommand(program, registry);
|
|
8574
8811
|
registerConfigCommand(program, registry);
|
|
8575
8812
|
registerTemplateCommand(program, registry);
|
|
8576
|
-
registerUpdateCommand(program
|
|
8813
|
+
registerUpdateCommand(program);
|
|
8577
8814
|
program.command("doctor").description("\u8BCA\u65AD\u9879\u76EE DeepStorm \u914D\u7F6E\u72B6\u6001").action(() => {
|
|
8578
8815
|
const report = runDoctor(process.cwd());
|
|
8579
8816
|
printDoctorReport(report);
|