@deepstorm/cli 0.9.0 → 0.9.1
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 +177 -60
- package/dist/skills/reef-commit/SKILL.md +1 -1
- package/dist/skills/reef-scope/SKILL.md +1 -3
- package/dist/skills/sweep-init/SKILL.md +5 -11
- package/dist/skills/sweep-plan/SKILL.md.tmpl +2 -13
- package/dist/skills/sweep-run/SKILL.md +6 -17
- package/dist/skills/sweep-run/scripts/env-manager.mjs +30 -50
- package/package.json +2 -2
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(path24) {
|
|
1191
|
+
return /^\.|this\b/.test(path24.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(path24) {
|
|
1196
|
+
return path24.parts.length === 1 && !AST.helpers.scopedId(path24) && !path24.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(path24, 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: path24,
|
|
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), path24 = decorator.path;
|
|
2590
2590
|
this.useDecorators = true;
|
|
2591
|
-
this.opcode("registerDecorator", params.length,
|
|
2591
|
+
this.opcode("registerDecorator", params.length, path24.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 path24 = sexpr.path, name = path24.parts[0], isBlock = program2 != null || inverse != null;
|
|
2656
|
+
this.opcode("getContext", path24.depth);
|
|
2657
2657
|
this.opcode("pushProgram", program2);
|
|
2658
2658
|
this.opcode("pushProgram", inverse);
|
|
2659
|
-
|
|
2660
|
-
this.accept(
|
|
2659
|
+
path24.strict = true;
|
|
2660
|
+
this.accept(path24);
|
|
2661
2661
|
this.opcode("invokeAmbiguous", name, isBlock);
|
|
2662
2662
|
},
|
|
2663
2663
|
simpleSexpr: function simpleSexpr(sexpr) {
|
|
2664
|
-
var
|
|
2665
|
-
|
|
2666
|
-
this.accept(
|
|
2664
|
+
var path24 = sexpr.path;
|
|
2665
|
+
path24.strict = true;
|
|
2666
|
+
this.accept(path24);
|
|
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), path24 = sexpr.path, name = path24.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
|
+
path24.strict = true;
|
|
2677
|
+
path24.falsy = true;
|
|
2678
|
+
this.accept(path24);
|
|
2679
|
+
this.opcode("invokeHelper", params.length, path24.original, _ast2["default"].helpers.simpleId(path24));
|
|
2680
2680
|
}
|
|
2681
2681
|
},
|
|
2682
|
-
PathExpression: function PathExpression(
|
|
2683
|
-
this.addDepth(
|
|
2684
|
-
this.opcode("getContext",
|
|
2685
|
-
var name =
|
|
2682
|
+
PathExpression: function PathExpression(path24) {
|
|
2683
|
+
this.addDepth(path24.depth);
|
|
2684
|
+
this.opcode("getContext", path24.depth);
|
|
2685
|
+
var name = path24.parts[0], scoped = _ast2["default"].helpers.scopedId(path24), blockParamId = !path24.depth && !scoped && this.blockParamIndex(name);
|
|
2686
2686
|
if (blockParamId) {
|
|
2687
|
-
this.opcode("lookupBlockParam", blockParamId,
|
|
2687
|
+
this.opcode("lookupBlockParam", blockParamId, path24.parts);
|
|
2688
2688
|
} else if (!name) {
|
|
2689
2689
|
this.opcode("pushContext");
|
|
2690
|
-
} else if (
|
|
2690
|
+
} else if (path24.data) {
|
|
2691
2691
|
this.options.data = true;
|
|
2692
|
-
this.opcode("lookupData",
|
|
2692
|
+
this.opcode("lookupData", path24.depth, path24.parts, path24.strict);
|
|
2693
2693
|
} else {
|
|
2694
|
-
this.opcode("lookupOnContext",
|
|
2694
|
+
this.opcode("lookupOnContext", path24.parts, path24.falsy, path24.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 path24 = aPath;
|
|
3045
3045
|
var url = urlParse(aPath);
|
|
3046
3046
|
if (url) {
|
|
3047
3047
|
if (!url.path) {
|
|
3048
3048
|
return aPath;
|
|
3049
3049
|
}
|
|
3050
|
-
|
|
3050
|
+
path24 = url.path;
|
|
3051
3051
|
}
|
|
3052
|
-
var isAbsolute = exports2.isAbsolute(
|
|
3053
|
-
var parts =
|
|
3052
|
+
var isAbsolute = exports2.isAbsolute(path24);
|
|
3053
|
+
var parts = path24.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
|
+
path24 = parts.join("/");
|
|
3071
|
+
if (path24 === "") {
|
|
3072
|
+
path24 = isAbsolute ? "/" : ".";
|
|
3073
3073
|
}
|
|
3074
3074
|
if (url) {
|
|
3075
|
-
url.path =
|
|
3075
|
+
url.path = path24;
|
|
3076
3076
|
return urlGenerate(url);
|
|
3077
3077
|
}
|
|
3078
|
-
return
|
|
3078
|
+
return path24;
|
|
3079
3079
|
}
|
|
3080
3080
|
exports2.normalize = normalize;
|
|
3081
|
-
function
|
|
3081
|
+
function join22(aRoot, aPath) {
|
|
3082
3082
|
if (aRoot === "") {
|
|
3083
3083
|
aRoot = ".";
|
|
3084
3084
|
}
|
|
@@ -3110,7 +3110,7 @@ var require_util = __commonJS({
|
|
|
3110
3110
|
}
|
|
3111
3111
|
return joined;
|
|
3112
3112
|
}
|
|
3113
|
-
exports2.join =
|
|
3113
|
+
exports2.join = join22;
|
|
3114
3114
|
exports2.isAbsolute = function(aPath) {
|
|
3115
3115
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
3116
3116
|
};
|
|
@@ -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 = join22(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 path24 = id.parts.join("/");
|
|
5862
|
+
return (id.data ? "@" : "") + "PATH:" + path24;
|
|
5863
5863
|
};
|
|
5864
5864
|
PrintVisitor.prototype.StringLiteral = function(string) {
|
|
5865
5865
|
return '"' + string.value + '"';
|
|
@@ -5912,7 +5912,7 @@ var require_lib = __commonJS({
|
|
|
5912
5912
|
// src/index.ts
|
|
5913
5913
|
var import_commander = require("commander");
|
|
5914
5914
|
var fs27 = __toESM(require("node:fs"));
|
|
5915
|
-
var
|
|
5915
|
+
var path23 = __toESM(require("node:path"));
|
|
5916
5916
|
|
|
5917
5917
|
// src/commands/setup.ts
|
|
5918
5918
|
var path9 = __toESM(require("node:path"));
|
|
@@ -9383,6 +9383,7 @@ function registerTemplateCommand(program2, registry2) {
|
|
|
9383
9383
|
|
|
9384
9384
|
// src/commands/update.ts
|
|
9385
9385
|
var fs24 = __toESM(require("node:fs"));
|
|
9386
|
+
var path20 = __toESM(require("node:path"));
|
|
9386
9387
|
var import_node_child_process2 = require("node:child_process");
|
|
9387
9388
|
|
|
9388
9389
|
// src/utils/version.ts
|
|
@@ -9814,23 +9815,139 @@ async function updateCLI(fetchFn) {
|
|
|
9814
9815
|
return result;
|
|
9815
9816
|
}
|
|
9816
9817
|
function getInstalledSkillIds(targetDir) {
|
|
9817
|
-
const
|
|
9818
|
+
const config = readDeepStormConfig(targetDir);
|
|
9819
|
+
if (!config) return [];
|
|
9820
|
+
const ids = config.installedSkills;
|
|
9821
|
+
return Array.isArray(ids) ? ids : [];
|
|
9822
|
+
}
|
|
9823
|
+
function migrateOldDataSources(targetDir) {
|
|
9824
|
+
const migrated = [];
|
|
9818
9825
|
try {
|
|
9819
|
-
const
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9826
|
+
const claudeSettingsPath = path20.join(targetDir, ".claude", "settings.json");
|
|
9827
|
+
if (fs24.existsSync(claudeSettingsPath)) {
|
|
9828
|
+
const raw = fs24.readFileSync(claudeSettingsPath, "utf-8");
|
|
9829
|
+
const claudeConfig = JSON.parse(raw);
|
|
9830
|
+
if (claudeConfig.deepstorm && typeof claudeConfig.deepstorm === "object" && Object.keys(claudeConfig.deepstorm).length > 0) {
|
|
9831
|
+
writeDeepStormConfig(targetDir, claudeConfig.deepstorm);
|
|
9832
|
+
delete claudeConfig.deepstorm;
|
|
9833
|
+
fs24.writeFileSync(claudeSettingsPath, JSON.stringify(claudeConfig, null, 2) + "\n", "utf-8");
|
|
9834
|
+
migrated.push(".claude/settings.json \u2192 .deepstorm/settings.json");
|
|
9835
|
+
console.log(" \u2714 \u5DF2\u8FC1\u79FB .claude/settings.json \u4E2D\u7684 DeepStorm \u914D\u7F6E");
|
|
9836
|
+
}
|
|
9837
|
+
}
|
|
9838
|
+
} catch (err) {
|
|
9839
|
+
console.log(` \u26A0 deepstorm \u914D\u7F6E\u8FC1\u79FB\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
9840
|
+
}
|
|
9841
|
+
try {
|
|
9842
|
+
const sweepInitPath = path20.join(targetDir, ".sweep-init");
|
|
9843
|
+
if (fs24.existsSync(sweepInitPath)) {
|
|
9844
|
+
const existing = readDeepStormConfig(targetDir);
|
|
9845
|
+
const hasE2ePath = existing && existing.sweep?.e2eProjectPath;
|
|
9846
|
+
if (!hasE2ePath) {
|
|
9847
|
+
writeDeepStormConfig(targetDir, { sweep: { e2eProjectPath: "." } });
|
|
9848
|
+
migrated.push(".sweep-init \u2192 sweep.e2eProjectPath");
|
|
9849
|
+
console.log(' \u2714 \u5DF2\u8FC1\u79FB .sweep-init \u2192 sweep.e2eProjectPath = "."');
|
|
9850
|
+
}
|
|
9851
|
+
fs24.rmSync(sweepInitPath, { force: true });
|
|
9852
|
+
if (hasE2ePath) {
|
|
9853
|
+
console.log(" \u2139 .sweep-init \u5DF2\u5220\u9664\uFF08sweep.e2eProjectPath \u5DF2\u5B58\u5728\uFF0C\u672A\u8986\u76D6\uFF09");
|
|
9854
|
+
}
|
|
9855
|
+
}
|
|
9856
|
+
} catch (err) {
|
|
9857
|
+
console.log(` \u26A0 .sweep-init \u8FC1\u79FB\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
9858
|
+
}
|
|
9859
|
+
try {
|
|
9860
|
+
const envPath = path20.join(targetDir, ".env");
|
|
9861
|
+
if (fs24.existsSync(envPath)) {
|
|
9862
|
+
const raw = fs24.readFileSync(envPath, "utf-8");
|
|
9863
|
+
const lines = raw.split("\n");
|
|
9864
|
+
const baseUrlVars = {};
|
|
9865
|
+
let defaultEnv = "test";
|
|
9866
|
+
let hasDefaultEnv = false;
|
|
9867
|
+
const remainingLines = [];
|
|
9868
|
+
for (const line of lines) {
|
|
9869
|
+
const trimmed = line.trim();
|
|
9870
|
+
const baseMatch = trimmed.match(/^BASE_URL_(\w+)=(.+)$/);
|
|
9871
|
+
if (baseMatch) {
|
|
9872
|
+
const envName = baseMatch[1].toLowerCase();
|
|
9873
|
+
let url = baseMatch[2].trim();
|
|
9874
|
+
if (url.startsWith('"') && url.endsWith('"') || url.startsWith("'") && url.endsWith("'")) {
|
|
9875
|
+
url = url.slice(1, -1);
|
|
9876
|
+
}
|
|
9877
|
+
baseUrlVars[envName] = url;
|
|
9878
|
+
continue;
|
|
9879
|
+
}
|
|
9880
|
+
const defaultMatch = trimmed.match(/^DEFAULT_ENV=(.+)$/);
|
|
9881
|
+
if (defaultMatch) {
|
|
9882
|
+
hasDefaultEnv = true;
|
|
9883
|
+
defaultEnv = defaultMatch[1].trim();
|
|
9884
|
+
continue;
|
|
9885
|
+
}
|
|
9886
|
+
remainingLines.push(line);
|
|
9887
|
+
}
|
|
9888
|
+
if (Object.keys(baseUrlVars).length > 0) {
|
|
9889
|
+
const environments = {};
|
|
9890
|
+
for (const [envName, url] of Object.entries(baseUrlVars)) {
|
|
9891
|
+
environments[envName] = { baseUrl: url };
|
|
9892
|
+
}
|
|
9893
|
+
environments.default = defaultEnv;
|
|
9894
|
+
const existing = readDeepStormConfig(targetDir);
|
|
9895
|
+
const hasEnvs = existing && existing.sweep?.environments;
|
|
9896
|
+
if (!hasEnvs) {
|
|
9897
|
+
writeDeepStormConfig(targetDir, { sweep: { environments } });
|
|
9898
|
+
migrated.push(".env BASE_URL \u2192 sweep.environments");
|
|
9899
|
+
console.log(` \u2714 \u5DF2\u8FC1\u79FB .env \u4E2D ${Object.keys(baseUrlVars).length} \u4E2A\u73AF\u5883\u914D\u7F6E`);
|
|
9900
|
+
}
|
|
9901
|
+
const cleaned = remainingLines.join("\n").trimEnd();
|
|
9902
|
+
if (cleaned === "") {
|
|
9903
|
+
fs24.writeFileSync(envPath, "# \u73AF\u5883 baseURL \u914D\u7F6E\u5DF2\u8FC1\u79FB\u81F3 .deepstorm/settings.json\n# \u8BF7\u52FF\u5728\u6B64\u5904\u91CD\u590D\u5B9A\u4E49 BASE_URL_* \u914D\u7F6E\n", "utf-8");
|
|
9904
|
+
} else if (hasDefaultEnv || Object.keys(baseUrlVars).length > 0) {
|
|
9905
|
+
fs24.writeFileSync(envPath, cleaned + "\n", "utf-8");
|
|
9906
|
+
}
|
|
9907
|
+
}
|
|
9908
|
+
}
|
|
9909
|
+
} catch (err) {
|
|
9910
|
+
console.log(` \u26A0 .env baseURL \u8FC1\u79FB\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
9824
9911
|
}
|
|
9912
|
+
try {
|
|
9913
|
+
const scopeConfigPath = path20.join(targetDir, ".deepstorm", "scope-config.json");
|
|
9914
|
+
if (fs24.existsSync(scopeConfigPath)) {
|
|
9915
|
+
const raw = fs24.readFileSync(scopeConfigPath, "utf-8");
|
|
9916
|
+
const scopeData = JSON.parse(raw);
|
|
9917
|
+
const scope = {};
|
|
9918
|
+
if ("enabled" in scopeData) scope.enabled = scopeData.enabled;
|
|
9919
|
+
if ("ciEnabled" in scopeData) scope.ciEnabled = scopeData.ciEnabled;
|
|
9920
|
+
if ("domains" in scopeData) scope.domains = scopeData.domains;
|
|
9921
|
+
const existing = readDeepStormConfig(targetDir);
|
|
9922
|
+
const hasReefScope = existing && existing.reef?.scope;
|
|
9923
|
+
if (!hasReefScope) {
|
|
9924
|
+
writeDeepStormConfig(targetDir, { reef: { scope } });
|
|
9925
|
+
migrated.push("scope-config.json \u2192 reef.scope");
|
|
9926
|
+
console.log(" \u2714 \u5DF2\u8FC1\u79FB .deepstorm/scope-config.json \u2192 reef.scope");
|
|
9927
|
+
}
|
|
9928
|
+
fs24.rmSync(scopeConfigPath, { force: true });
|
|
9929
|
+
if (hasReefScope) {
|
|
9930
|
+
console.log(" \u2139 scope-config.json \u5DF2\u5220\u9664\uFF08reef.scope \u5DF2\u5B58\u5728\uFF0C\u672A\u8986\u76D6\uFF09");
|
|
9931
|
+
}
|
|
9932
|
+
}
|
|
9933
|
+
} catch (err) {
|
|
9934
|
+
console.log(` \u26A0 scope-config.json \u8FC1\u79FB\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
9935
|
+
}
|
|
9936
|
+
return { migrated };
|
|
9825
9937
|
}
|
|
9826
9938
|
function registerUpdateCommand(program2) {
|
|
9827
9939
|
const cliDir2 = __dirname;
|
|
9828
9940
|
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 () => {
|
|
9829
|
-
const
|
|
9941
|
+
const targetDir = process.cwd();
|
|
9942
|
+
const { migrated } = migrateOldDataSources(targetDir);
|
|
9943
|
+
if (migrated.length > 0) {
|
|
9944
|
+
console.log(`\u2714 \u5DF2\u5B8C\u6210 ${migrated.length} \u9879\u65E7\u6570\u636E\u6E90\u8FC1\u79FB`);
|
|
9945
|
+
}
|
|
9946
|
+
const installedIds = getInstalledSkillIds(targetDir);
|
|
9830
9947
|
if (installedIds.length === 0) {
|
|
9831
9948
|
console.log("\u672A\u68C0\u6D4B\u5230\u5DF2\u5B89\u88C5\u7684 skill\uFF0C\u8DF3\u8FC7\u540C\u6B65");
|
|
9832
9949
|
} else {
|
|
9833
|
-
upgradeTemplates(cliDir2,
|
|
9950
|
+
upgradeTemplates(cliDir2, targetDir, installedIds);
|
|
9834
9951
|
}
|
|
9835
9952
|
await updateCLI();
|
|
9836
9953
|
});
|
|
@@ -9844,7 +9961,7 @@ function registerPilotCommands(program2) {
|
|
|
9844
9961
|
|
|
9845
9962
|
// src/commands/doctor.ts
|
|
9846
9963
|
var fs25 = __toESM(require("node:fs"));
|
|
9847
|
-
var
|
|
9964
|
+
var path21 = __toESM(require("node:path"));
|
|
9848
9965
|
function getInstalledSkills(targetDir) {
|
|
9849
9966
|
const settingsPath = getDeepStormConfigPath(targetDir);
|
|
9850
9967
|
try {
|
|
@@ -9896,15 +10013,15 @@ function runDoctor(targetDir) {
|
|
|
9896
10013
|
});
|
|
9897
10014
|
}
|
|
9898
10015
|
}
|
|
9899
|
-
const skillsDir =
|
|
10016
|
+
const skillsDir = path21.join(targetDir, ".claude", "skills");
|
|
9900
10017
|
if (fs25.existsSync(skillsDir)) {
|
|
9901
10018
|
const skillDirs = fs25.readdirSync(skillsDir).filter(
|
|
9902
|
-
(n) => fs25.statSync(
|
|
10019
|
+
(n) => fs25.statSync(path21.join(skillsDir, n)).isDirectory()
|
|
9903
10020
|
);
|
|
9904
10021
|
let validCount = 0;
|
|
9905
10022
|
let invalidCount = 0;
|
|
9906
10023
|
for (const skillName of skillDirs) {
|
|
9907
|
-
const skillMd =
|
|
10024
|
+
const skillMd = path21.join(skillsDir, skillName, "SKILL.md");
|
|
9908
10025
|
if (!fs25.existsSync(skillMd)) {
|
|
9909
10026
|
invalidCount++;
|
|
9910
10027
|
continue;
|
|
@@ -9939,7 +10056,7 @@ function runDoctor(targetDir) {
|
|
|
9939
10056
|
const installedSkills = getInstalledSkills(targetDir);
|
|
9940
10057
|
const missingSkills = [];
|
|
9941
10058
|
for (const skillId of installedSkills) {
|
|
9942
|
-
if (!fs25.existsSync(
|
|
10059
|
+
if (!fs25.existsSync(path21.join(skillsDir, skillId))) {
|
|
9943
10060
|
missingSkills.push(skillId);
|
|
9944
10061
|
}
|
|
9945
10062
|
}
|
|
@@ -9963,7 +10080,7 @@ function runDoctor(targetDir) {
|
|
|
9963
10080
|
message: ".claude/skills/ \u4E0D\u5B58\u5728"
|
|
9964
10081
|
});
|
|
9965
10082
|
}
|
|
9966
|
-
const mcpPath =
|
|
10083
|
+
const mcpPath = path21.join(targetDir, ".mcp.json");
|
|
9967
10084
|
if (fs25.existsSync(mcpPath)) {
|
|
9968
10085
|
try {
|
|
9969
10086
|
const mcp = JSON.parse(fs25.readFileSync(mcpPath, "utf-8"));
|
|
@@ -10085,7 +10202,7 @@ function printDoctorReport(report) {
|
|
|
10085
10202
|
|
|
10086
10203
|
// src/commands/uninstall.ts
|
|
10087
10204
|
var fs26 = __toESM(require("node:fs"));
|
|
10088
|
-
var
|
|
10205
|
+
var path22 = __toESM(require("node:path"));
|
|
10089
10206
|
var import_prompts4 = require("@clack/prompts");
|
|
10090
10207
|
async function uninstallDeepStorm(targetDir) {
|
|
10091
10208
|
const settingsPath = getDeepStormConfigPath(targetDir);
|
|
@@ -10105,7 +10222,7 @@ async function uninstallDeepStorm(targetDir) {
|
|
|
10105
10222
|
}
|
|
10106
10223
|
cleanInstalled(targetDir);
|
|
10107
10224
|
resetConfig(targetDir);
|
|
10108
|
-
const templatesDir =
|
|
10225
|
+
const templatesDir = path22.join(targetDir, ".deepstorm", "templates");
|
|
10109
10226
|
if (fs26.existsSync(templatesDir)) {
|
|
10110
10227
|
const shouldDelete = await (0, import_prompts4.confirm)({
|
|
10111
10228
|
message: "\u662F\u5426\u5220\u9664 .deepstorm/templates/ \u76EE\u5F55\uFF1F",
|
|
@@ -10125,7 +10242,7 @@ async function uninstallDeepStorm(targetDir) {
|
|
|
10125
10242
|
var program = new import_commander.Command();
|
|
10126
10243
|
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");
|
|
10127
10244
|
function loadRegistry() {
|
|
10128
|
-
const registryPath =
|
|
10245
|
+
const registryPath = path23.join(__dirname, "registry.json");
|
|
10129
10246
|
try {
|
|
10130
10247
|
const raw = fs27.readFileSync(registryPath, "utf-8");
|
|
10131
10248
|
return JSON.parse(raw);
|
|
@@ -137,7 +137,7 @@ if [ -f "$SCOPE_HOOK" ]; then
|
|
|
137
137
|
bash "$SCOPE_HOOK" || {
|
|
138
138
|
echo ""
|
|
139
139
|
echo "提示:如需继续提交,请使用 'reef-scope-split.sh' 拆分分支"
|
|
140
|
-
echo "或临时禁用 scope 检查(不推荐):
|
|
140
|
+
echo "或临时禁用 scope 检查(不推荐):settings.json → reef.scope.enabled: false"
|
|
141
141
|
exit 1
|
|
142
142
|
}
|
|
143
143
|
fi
|
|
@@ -89,8 +89,6 @@ bash packages/reef/hooks/reef-scope-split.sh
|
|
|
89
89
|
- `ciEnabled`: CI 门禁开关(独立控制)
|
|
90
90
|
- `domains`: 项目业务领域列表(空 = AI 自由分类,非空 = AI 对齐到这些领域)
|
|
91
91
|
|
|
92
|
-
> **注意:** 旧版 `.deepstorm/scope-config.json` 已不再使用。如果存在该文件,运行 `deepstorm scope setup` 会自动迁移到 `settings.json`。
|
|
93
|
-
|
|
94
92
|
## 使用流程
|
|
95
93
|
|
|
96
94
|
1. **安装**: 运行一次 `reef-scope-setup.sh install`
|
|
@@ -128,7 +126,7 @@ scope-check:
|
|
|
128
126
|
## 常见问题
|
|
129
127
|
|
|
130
128
|
**Q: 我不想在所有项目上都启用这个检查?**
|
|
131
|
-
A:
|
|
129
|
+
A: 每个项目独立安装和配置,settings.json 中 `reef.scope.enabled: false` 可关闭。
|
|
132
130
|
|
|
133
131
|
**Q: 我改了文档也要被阻断吗?**
|
|
134
132
|
A: 不会。文档(markdown、README 等)变更会被归类为 `documentation` 领域,不计入多领域阻断判断。
|
|
@@ -93,18 +93,12 @@ E2E_PATH=$(cat .deepstorm/settings.json 2>/dev/null | grep -o '"e2eProjectPath"[
|
|
|
93
93
|
|
|
94
94
|
#### 1.2 已初始化 → 退出
|
|
95
95
|
|
|
96
|
-
- **WHEN** `sweep.e2eProjectPath`
|
|
97
|
-
- **THEN** 提示"当前项目已初始化为 Sweep 测试项目。如需重新初始化,请删除 `sweep.e2eProjectPath`
|
|
96
|
+
- **WHEN** `sweep.e2eProjectPath` 已设置
|
|
97
|
+
- **THEN** 提示"当前项目已初始化为 Sweep 测试项目。如需重新初始化,请删除 `sweep.e2eProjectPath` 配置后重试。"并退出
|
|
98
98
|
|
|
99
|
-
#### 1.3
|
|
99
|
+
#### 1.3 未初始化 → 继续
|
|
100
100
|
|
|
101
|
-
- **WHEN** `
|
|
102
|
-
- **THEN** 提示"ℹ️ 检测到旧版 .sweep-init 标记。建议删除该文件后重新运行 /sweep-init 以使用新版配置。"
|
|
103
|
-
- **THEN** 提示已初始化,退出
|
|
104
|
-
|
|
105
|
-
#### 1.4 未初始化 → 继续
|
|
106
|
-
|
|
107
|
-
- **WHEN** 以上均不满足
|
|
101
|
+
- **WHEN** `sweep.e2eProjectPath` 未设置
|
|
108
102
|
- **THEN** 继续执行初始化流程
|
|
109
103
|
|
|
110
104
|
---
|
|
@@ -375,7 +369,7 @@ fi
|
|
|
375
369
|
|
|
376
370
|
- [ ] 已读取框架配置(`deepstorm.sweep.e2eFramework`)
|
|
377
371
|
- [ ] 步骤 0A:已选择目标目录(`TARGET_DIR` 已确定)
|
|
378
|
-
- [ ] 步骤 1:检查通过(`e2eProjectPath`
|
|
372
|
+
- [ ] 步骤 1:检查通过(`e2eProjectPath` 未设置)
|
|
379
373
|
- [ ] 项目目录结构已创建(`{TARGET_DIR}/flows/`、`{TARGET_DIR}/flows/reports/`、`{TARGET_DIR}/scripts/`)
|
|
380
374
|
- [ ] package.json 已写入(含对应框架的依赖)
|
|
381
375
|
- [ ] 框架配置文件已生成(如 playwright.config.ts)
|
|
@@ -90,21 +90,10 @@ fi
|
|
|
90
90
|
fi
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
#### 1.3 配置不存在 →
|
|
93
|
+
#### 1.3 配置不存在 → 报错退出
|
|
94
94
|
|
|
95
95
|
- **WHEN** `E2E_PATH` 为空
|
|
96
|
-
- **THEN**
|
|
97
|
-
```bash
|
|
98
|
-
if [ -f ".sweep-init" ]; then
|
|
99
|
-
echo "ℹ️ 检测到旧版 .sweep-init 标记。建议运行 /sweep-init 刷新配置。"
|
|
100
|
-
# 继续执行(兼容旧项目)
|
|
101
|
-
elif [ -n "$DEEPSTORM_DIR" ] && [ -f "$DEEPSTORM_DIR/.sweep-init" ]; then
|
|
102
|
-
echo "ℹ️ 检测到旧版 .sweep-init 标记(项目根: $DEEPSTORM_DIR)。建议运行 /sweep-init 刷新配置。"
|
|
103
|
-
else
|
|
104
|
-
echo "❌ 未检测到 E2E 项目。请先运行 /sweep-init 初始化。"
|
|
105
|
-
exit 1
|
|
106
|
-
fi
|
|
107
|
-
```
|
|
96
|
+
- **THEN** 提示"❌ 未检测到 E2E 项目。请先运行 /sweep-init 初始化。"并退出
|
|
108
97
|
|
|
109
98
|
### 步骤 2:获取测试需求上下文(MCP 动态适配)
|
|
110
99
|
|
|
@@ -102,21 +102,10 @@ fi
|
|
|
102
102
|
fi
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
#### 1.2 配置不存在 →
|
|
105
|
+
#### 1.2 配置不存在 → 报错退出
|
|
106
106
|
|
|
107
107
|
- **WHEN** `E2E_PATH` 为空
|
|
108
|
-
- **THEN**
|
|
109
|
-
```bash
|
|
110
|
-
if [ -f ".sweep-init" ]; then
|
|
111
|
-
echo "ℹ️ 检测到旧版 .sweep-init 标记。建议运行 /sweep-init 刷新配置。"
|
|
112
|
-
# 继续执行(兼容旧项目)
|
|
113
|
-
elif [ -n "$DEEPSTORM_DIR" ] && [ -f "$DEEPSTORM_DIR/.sweep-init" ]; then
|
|
114
|
-
echo "ℹ️ 检测到旧版 .sweep-init 标记(项目根: $DEEPSTORM_DIR)。建议运行 /sweep-init 刷新配置。"
|
|
115
|
-
else
|
|
116
|
-
echo "❌ 未检测到 E2E 项目。请先运行 /sweep-init 初始化。"
|
|
117
|
-
exit 1
|
|
118
|
-
fi
|
|
119
|
-
```
|
|
108
|
+
- **THEN** 提示"❌ 未检测到 E2E 项目。请先运行 /sweep-init 初始化。"并退出
|
|
120
109
|
|
|
121
110
|
---
|
|
122
111
|
|
|
@@ -217,9 +206,9 @@ node scripts/env-manager.mjs --env staging
|
|
|
217
206
|
]}
|
|
218
207
|
```
|
|
219
208
|
|
|
220
|
-
- `--env staging` → 从 `settings.json` 的 `sweep.environments.staging`
|
|
221
|
-
- `--env test` → 从 `settings.json` 的 `sweep.environments.test`
|
|
222
|
-
- 不传参 → 使用 `settings.json` 的 `sweep.environments.default
|
|
209
|
+
- `--env staging` → 从 `settings.json` 的 `sweep.environments.staging` 读取
|
|
210
|
+
- `--env test` → 从 `settings.json` 的 `sweep.environments.test` 读取
|
|
211
|
+
- 不传参 → 使用 `settings.json` 的 `sweep.environments.default`,未设置则默认 `test`
|
|
223
212
|
|
|
224
213
|
#### 4.2 设置环境变量
|
|
225
214
|
|
|
@@ -234,7 +223,7 @@ BASE_URL=$(node scripts/env-manager.mjs --env test | node -pe "JSON.parse(requir
|
|
|
234
223
|
|
|
235
224
|
#### 4.3 环境不存在处理
|
|
236
225
|
|
|
237
|
-
如果 `baseUrl` 为 `null`(指定的环境在
|
|
226
|
+
如果 `baseUrl` 为 `null`(指定的环境在 settings.json 中找不到对应配置):
|
|
238
227
|
|
|
239
228
|
- 提示"未找到 [{env}] 环境的 baseURL 配置"
|
|
240
229
|
- 列出 `availableEnvs` 中已有的环境
|
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Env Manager — 测试环境配置管理
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* 从 .deepstorm/settings.json 读取目标环境配置,输出结构化结果。
|
|
7
7
|
* 支持检查 E2E 框架配置和 MCP 可用性。
|
|
8
8
|
*
|
|
9
|
+
* 所有旧数据源(.env BASE_URL、.sweep-init、scope-config.json 等)
|
|
10
|
+
* 已由 `deepstorm update` 统一迁移到 .deepstorm/settings.json,
|
|
11
|
+
* 本文件无需再做兼容处理。
|
|
12
|
+
*
|
|
9
13
|
* Usage:
|
|
10
14
|
* node env-manager.mjs --env test # 解析指定环境
|
|
11
15
|
* node env-manager.mjs --env test --print # 输出 export 语句
|
|
@@ -126,49 +130,35 @@ export function readDotEnv() {
|
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
/**
|
|
129
|
-
* Get the default environment name.
|
|
130
|
-
* Priority: settings.json > .env
|
|
133
|
+
* Get the default environment name from .deepstorm/settings.json.
|
|
131
134
|
* Falls back to 'test' if not configured.
|
|
132
135
|
*/
|
|
133
|
-
export function getDefaultEnv(
|
|
136
|
+
export function getDefaultEnv() {
|
|
134
137
|
const dsEnvs = readDeepstormEnvironments();
|
|
135
138
|
if (dsEnvs && dsEnvs.default) {
|
|
136
139
|
return dsEnvs.default;
|
|
137
140
|
}
|
|
138
|
-
return
|
|
141
|
+
return 'test';
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
/**
|
|
142
|
-
* List all available environments.
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
+
* List all available environments from .deepstorm/settings.json.
|
|
146
|
+
*
|
|
147
|
+
* Reads sweep.environments and returns environment name + URL pairs.
|
|
148
|
+
* Returns empty array if not configured.
|
|
145
149
|
*/
|
|
146
|
-
export function listEnvs(
|
|
150
|
+
export function listEnvs() {
|
|
147
151
|
const dsEnvs = readDeepstormEnvironments();
|
|
148
|
-
if (dsEnvs)
|
|
149
|
-
const envs = [];
|
|
150
|
-
for (const [name, config] of Object.entries(dsEnvs)) {
|
|
151
|
-
if (name === 'default') continue;
|
|
152
|
-
if (config && config.baseUrl) {
|
|
153
|
-
envs.push({
|
|
154
|
-
name: name.toLowerCase(),
|
|
155
|
-
key: `BASE_URL_${name.toUpperCase()}`,
|
|
156
|
-
url: config.baseUrl,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return envs;
|
|
161
|
-
}
|
|
152
|
+
if (!dsEnvs) return [];
|
|
162
153
|
|
|
163
|
-
// Fallback to .env-based envMap
|
|
164
154
|
const envs = [];
|
|
165
|
-
for (const
|
|
166
|
-
|
|
167
|
-
if (
|
|
155
|
+
for (const [name, config] of Object.entries(dsEnvs)) {
|
|
156
|
+
if (name === 'default') continue;
|
|
157
|
+
if (config && config.baseUrl) {
|
|
168
158
|
envs.push({
|
|
169
|
-
name:
|
|
170
|
-
key:
|
|
171
|
-
url:
|
|
159
|
+
name: name.toLowerCase(),
|
|
160
|
+
key: `BASE_URL_${name.toUpperCase()}`,
|
|
161
|
+
url: config.baseUrl,
|
|
172
162
|
});
|
|
173
163
|
}
|
|
174
164
|
}
|
|
@@ -176,36 +166,27 @@ export function listEnvs(envMap) {
|
|
|
176
166
|
}
|
|
177
167
|
|
|
178
168
|
/**
|
|
179
|
-
* Resolve target environment config.
|
|
180
|
-
*
|
|
181
|
-
* Priority: settings.json > .env
|
|
169
|
+
* Resolve target environment config from .deepstorm/settings.json.
|
|
182
170
|
*
|
|
183
171
|
* @param {string} [envName] - Target environment name (e.g. 'staging', 'test')
|
|
184
172
|
* @returns {{ env: string, baseUrl: string|null, availableEnvs: Array<{name:string,url:string}> }}
|
|
185
173
|
*
|
|
186
174
|
* If envName is omitted, uses DEFAULT_ENV (or 'test').
|
|
175
|
+
* If settings.json has no environments config, baseUrl is null and availableEnvs is empty.
|
|
187
176
|
* If the environment is not found, baseUrl is null and availableEnvs lists alternatives.
|
|
188
177
|
*/
|
|
189
178
|
export function resolveEnv(envName) {
|
|
190
|
-
// Try settings.json first
|
|
191
179
|
const dsEnvs = readDeepstormEnvironments();
|
|
192
|
-
if (dsEnvs) {
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
const availableEnvs = listEnvs(envMap);
|
|
196
|
-
const baseUrlKey = `BASE_URL_${name.toUpperCase()}`;
|
|
197
|
-
const baseUrl = envMap[baseUrlKey] || null;
|
|
198
|
-
return { env: name, baseUrl, availableEnvs };
|
|
180
|
+
if (!dsEnvs) {
|
|
181
|
+
const name = envName || 'test';
|
|
182
|
+
return { env: name, baseUrl: null, availableEnvs: [] };
|
|
199
183
|
}
|
|
200
184
|
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
const
|
|
204
|
-
const availableEnvs = listEnvs(envMap);
|
|
205
|
-
|
|
185
|
+
const { envMap, defaultEnv } = deepstormEnvsToEnvMap(dsEnvs);
|
|
186
|
+
const name = envName || defaultEnv;
|
|
187
|
+
const availableEnvs = listEnvs();
|
|
206
188
|
const baseUrlKey = `BASE_URL_${name.toUpperCase()}`;
|
|
207
189
|
const baseUrl = envMap[baseUrlKey] || null;
|
|
208
|
-
|
|
209
190
|
return { env: name, baseUrl, availableEnvs };
|
|
210
191
|
}
|
|
211
192
|
|
|
@@ -263,9 +244,8 @@ if (process.argv[1] === import.meta.filename) {
|
|
|
263
244
|
const args = process.argv.slice(2);
|
|
264
245
|
|
|
265
246
|
if (args.includes('--list')) {
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
const defaultEnv = getDefaultEnv(envMap);
|
|
247
|
+
const envs = listEnvs();
|
|
248
|
+
const defaultEnv = getDefaultEnv();
|
|
269
249
|
console.log(JSON.stringify({ default: defaultEnv, environments: envs }));
|
|
270
250
|
process.exit(0);
|
|
271
251
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstorm/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "DeepStorm CLI — 一键配置项目开发环境",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "billkang",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dotenv": "^17.4.2",
|
|
17
17
|
"handlebars": "^4.7.8",
|
|
18
18
|
"js-yaml": "^4.1.0",
|
|
19
|
-
"@deepstorm/pilot": "^0.9.
|
|
19
|
+
"@deepstorm/pilot": "^0.9.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^22.0.0",
|