@nick848/sf-cli 1.0.4 → 1.0.7
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/CHANGELOG.md +29 -0
- package/dist/cli/index.js +250 -12
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.mts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +250 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +250 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1588,6 +1588,18 @@ declare class WorkflowEngine {
|
|
|
1588
1588
|
* 获取当前状态
|
|
1589
1589
|
*/
|
|
1590
1590
|
getState(): WorkflowState | null;
|
|
1591
|
+
/**
|
|
1592
|
+
* 获取所有活跃工作流
|
|
1593
|
+
*/
|
|
1594
|
+
getAllActiveWorkflows(): Promise<WorkflowState[]>;
|
|
1595
|
+
/**
|
|
1596
|
+
* 解析变更记录
|
|
1597
|
+
*/
|
|
1598
|
+
private parseChangeRecord;
|
|
1599
|
+
/**
|
|
1600
|
+
* 切换到指定工作流
|
|
1601
|
+
*/
|
|
1602
|
+
switchTo(changeId: string): Promise<boolean>;
|
|
1591
1603
|
/**
|
|
1592
1604
|
* 获取允许的下一步
|
|
1593
1605
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1588,6 +1588,18 @@ declare class WorkflowEngine {
|
|
|
1588
1588
|
* 获取当前状态
|
|
1589
1589
|
*/
|
|
1590
1590
|
getState(): WorkflowState | null;
|
|
1591
|
+
/**
|
|
1592
|
+
* 获取所有活跃工作流
|
|
1593
|
+
*/
|
|
1594
|
+
getAllActiveWorkflows(): Promise<WorkflowState[]>;
|
|
1595
|
+
/**
|
|
1596
|
+
* 解析变更记录
|
|
1597
|
+
*/
|
|
1598
|
+
private parseChangeRecord;
|
|
1599
|
+
/**
|
|
1600
|
+
* 切换到指定工作流
|
|
1601
|
+
*/
|
|
1602
|
+
switchTo(changeId: string): Promise<boolean>;
|
|
1591
1603
|
/**
|
|
1592
1604
|
* 获取允许的下一步
|
|
1593
1605
|
*/
|
package/dist/index.js
CHANGED
|
@@ -4114,6 +4114,92 @@ var WorkflowEngine = class {
|
|
|
4114
4114
|
getState() {
|
|
4115
4115
|
return this.state;
|
|
4116
4116
|
}
|
|
4117
|
+
/**
|
|
4118
|
+
* 获取所有活跃工作流
|
|
4119
|
+
*/
|
|
4120
|
+
async getAllActiveWorkflows() {
|
|
4121
|
+
const workflows = [];
|
|
4122
|
+
const changesDir = path4__namespace.join(this.openspecPath, "changes");
|
|
4123
|
+
try {
|
|
4124
|
+
const files = await fs4__namespace.readdir(changesDir);
|
|
4125
|
+
for (const file of files) {
|
|
4126
|
+
if (!file.endsWith(".md") || file.includes("-spec.md")) continue;
|
|
4127
|
+
const filePath = path4__namespace.join(changesDir, file);
|
|
4128
|
+
const content = await fs4__namespace.readFile(filePath, "utf-8");
|
|
4129
|
+
const state = this.parseChangeRecord(content);
|
|
4130
|
+
if (state && state.status === "running") {
|
|
4131
|
+
workflows.push(state);
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
} catch {
|
|
4135
|
+
}
|
|
4136
|
+
if (this.state && !workflows.find((w) => w.id === this.state?.id)) {
|
|
4137
|
+
workflows.unshift(this.state);
|
|
4138
|
+
}
|
|
4139
|
+
return workflows;
|
|
4140
|
+
}
|
|
4141
|
+
/**
|
|
4142
|
+
* 解析变更记录
|
|
4143
|
+
*/
|
|
4144
|
+
parseChangeRecord(content) {
|
|
4145
|
+
try {
|
|
4146
|
+
const idMatch = content.match(/^id:\s*(.+)$/m);
|
|
4147
|
+
const titleMatch = content.match(/^title:\s*(.+)$/m);
|
|
4148
|
+
const statusMatch = content.match(/^status:\s*(.+)$/m);
|
|
4149
|
+
const complexityMatch = content.match(/^complexity:\s*(\d+)/m);
|
|
4150
|
+
const workflowMatch = content.match(/^workflow:\s*(.+)$/m);
|
|
4151
|
+
const requirementMatch = content.match(/## 变更概述\s*\n+([\s\S]+?)(?=\n##|$)/);
|
|
4152
|
+
if (!idMatch || !titleMatch) return null;
|
|
4153
|
+
return {
|
|
4154
|
+
id: idMatch[1].trim(),
|
|
4155
|
+
title: titleMatch[1].trim(),
|
|
4156
|
+
status: statusMatch?.[1].trim() || "running",
|
|
4157
|
+
requirement: requirementMatch?.[1].trim() || "",
|
|
4158
|
+
complexity: parseInt(complexityMatch?.[1] || "5", 10),
|
|
4159
|
+
type: workflowMatch?.[1].trim() || "simple",
|
|
4160
|
+
currentStep: "propose",
|
|
4161
|
+
// 默认值,实际值需要从状态文件读取
|
|
4162
|
+
steps: [],
|
|
4163
|
+
artifacts: [],
|
|
4164
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
4165
|
+
};
|
|
4166
|
+
} catch {
|
|
4167
|
+
return null;
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
/**
|
|
4171
|
+
* 切换到指定工作流
|
|
4172
|
+
*/
|
|
4173
|
+
async switchTo(changeId) {
|
|
4174
|
+
if (this.state) {
|
|
4175
|
+
await this.saveState();
|
|
4176
|
+
}
|
|
4177
|
+
const statePath = path4__namespace.join(this.openspecPath, ".workflow-states", `${changeId}.json`);
|
|
4178
|
+
try {
|
|
4179
|
+
const content = await fs4__namespace.readFile(statePath, "utf-8");
|
|
4180
|
+
this.state = JSON.parse(content, (key, value) => {
|
|
4181
|
+
if (key.endsWith("At") && typeof value === "string") {
|
|
4182
|
+
return new Date(value);
|
|
4183
|
+
}
|
|
4184
|
+
return value;
|
|
4185
|
+
});
|
|
4186
|
+
await this.restoreSnapshots();
|
|
4187
|
+
return true;
|
|
4188
|
+
} catch {
|
|
4189
|
+
const changesDir = path4__namespace.join(this.openspecPath, "changes");
|
|
4190
|
+
const changeFile = path4__namespace.join(changesDir, `${changeId}.md`);
|
|
4191
|
+
try {
|
|
4192
|
+
const content = await fs4__namespace.readFile(changeFile, "utf-8");
|
|
4193
|
+
const parsed = this.parseChangeRecord(content);
|
|
4194
|
+
if (parsed && parsed.status === "running") {
|
|
4195
|
+
this.state = parsed;
|
|
4196
|
+
return true;
|
|
4197
|
+
}
|
|
4198
|
+
} catch {
|
|
4199
|
+
}
|
|
4200
|
+
return false;
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4117
4203
|
/**
|
|
4118
4204
|
* 获取允许的下一步
|
|
4119
4205
|
*/
|
|
@@ -4194,32 +4280,64 @@ var WorkflowEngine = class {
|
|
|
4194
4280
|
const changesDir = path4__namespace.join(this.openspecPath, "changes");
|
|
4195
4281
|
const archiveDir = path4__namespace.join(changesDir, "archive");
|
|
4196
4282
|
const specDir = path4__namespace.join(this.openspecPath, "spec");
|
|
4283
|
+
const statesDir = path4__namespace.join(this.openspecPath, ".workflow-states");
|
|
4197
4284
|
await fs4__namespace.mkdir(archiveDir, { recursive: true });
|
|
4198
4285
|
await fs4__namespace.mkdir(specDir, { recursive: true });
|
|
4286
|
+
await fs4__namespace.mkdir(statesDir, { recursive: true });
|
|
4199
4287
|
}
|
|
4200
4288
|
async restoreState() {
|
|
4201
|
-
const
|
|
4289
|
+
const activePath = path4__namespace.join(this.openspecPath, ".workflow-active.json");
|
|
4290
|
+
let activeId = null;
|
|
4202
4291
|
try {
|
|
4203
|
-
const
|
|
4292
|
+
const activeContent = await fs4__namespace.readFile(activePath, "utf-8");
|
|
4293
|
+
const activeData = JSON.parse(activeContent);
|
|
4294
|
+
activeId = activeData.activeId;
|
|
4295
|
+
} catch {
|
|
4296
|
+
}
|
|
4297
|
+
if (activeId) {
|
|
4298
|
+
const statePath = path4__namespace.join(this.openspecPath, ".workflow-states", `${activeId}.json`);
|
|
4299
|
+
try {
|
|
4300
|
+
const content = await fs4__namespace.readFile(statePath, "utf-8");
|
|
4301
|
+
this.state = JSON.parse(content, (key, value) => {
|
|
4302
|
+
if (key.endsWith("At") && typeof value === "string") {
|
|
4303
|
+
return new Date(value);
|
|
4304
|
+
}
|
|
4305
|
+
return value;
|
|
4306
|
+
});
|
|
4307
|
+
return;
|
|
4308
|
+
} catch {
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
4311
|
+
const oldStatePath = path4__namespace.join(this.openspecPath, ".workflow-state.json");
|
|
4312
|
+
try {
|
|
4313
|
+
const content = await fs4__namespace.readFile(oldStatePath, "utf-8");
|
|
4204
4314
|
this.state = JSON.parse(content, (key, value) => {
|
|
4205
4315
|
if (key.endsWith("At") && typeof value === "string") {
|
|
4206
4316
|
return new Date(value);
|
|
4207
4317
|
}
|
|
4208
4318
|
return value;
|
|
4209
4319
|
});
|
|
4320
|
+
if (this.state) {
|
|
4321
|
+
await this.saveState();
|
|
4322
|
+
await fs4__namespace.unlink(oldStatePath).catch(() => {
|
|
4323
|
+
});
|
|
4324
|
+
}
|
|
4210
4325
|
} catch (e) {
|
|
4211
4326
|
const err = e;
|
|
4212
4327
|
if (err.code !== "ENOENT") {
|
|
4213
4328
|
console.warn("\u8B66\u544A: \u5DE5\u4F5C\u6D41\u72B6\u6001\u6587\u4EF6\u5DF2\u635F\u574F\uFF0C\u5C06\u91CD\u65B0\u5F00\u59CB");
|
|
4214
|
-
await fs4__namespace.unlink(statePath).catch(() => {
|
|
4215
|
-
});
|
|
4216
4329
|
}
|
|
4217
4330
|
this.state = null;
|
|
4218
4331
|
}
|
|
4219
4332
|
}
|
|
4220
4333
|
async saveState() {
|
|
4221
|
-
|
|
4334
|
+
if (!this.state) return;
|
|
4335
|
+
const statesDir = path4__namespace.join(this.openspecPath, ".workflow-states");
|
|
4336
|
+
await fs4__namespace.mkdir(statesDir, { recursive: true });
|
|
4337
|
+
const statePath = path4__namespace.join(statesDir, `${this.state.id}.json`);
|
|
4222
4338
|
await fs4__namespace.writeFile(statePath, JSON.stringify(this.state, null, 2));
|
|
4339
|
+
const activePath = path4__namespace.join(this.openspecPath, ".workflow-active.json");
|
|
4340
|
+
await fs4__namespace.writeFile(activePath, JSON.stringify({ activeId: this.state.id }, null, 2));
|
|
4223
4341
|
}
|
|
4224
4342
|
async restoreSnapshots() {
|
|
4225
4343
|
const snapshotsPath = path4__namespace.join(this.openspecPath, ".workflow-snapshots.json");
|
|
@@ -5590,18 +5708,38 @@ var CommandType = /* @__PURE__ */ ((CommandType3) => {
|
|
|
5590
5708
|
var CommandParser = class {
|
|
5591
5709
|
slashCommands = [
|
|
5592
5710
|
"help",
|
|
5711
|
+
"h",
|
|
5712
|
+
"?",
|
|
5593
5713
|
"init",
|
|
5714
|
+
"i",
|
|
5594
5715
|
"new",
|
|
5716
|
+
"n",
|
|
5595
5717
|
"model",
|
|
5718
|
+
"m",
|
|
5596
5719
|
"update",
|
|
5720
|
+
"u",
|
|
5597
5721
|
"clear",
|
|
5722
|
+
"c",
|
|
5598
5723
|
"exit",
|
|
5724
|
+
"e",
|
|
5725
|
+
"q",
|
|
5726
|
+
"quit",
|
|
5727
|
+
"version",
|
|
5728
|
+
"v",
|
|
5729
|
+
// OpenSpec 工作流命令
|
|
5599
5730
|
"opsx:explore",
|
|
5600
5731
|
"opsx:new",
|
|
5601
5732
|
"opsx:continue",
|
|
5602
5733
|
"opsx:apply",
|
|
5603
5734
|
"opsx:archive",
|
|
5604
|
-
"opsx:propose"
|
|
5735
|
+
"opsx:propose",
|
|
5736
|
+
"opsx:status",
|
|
5737
|
+
"opsx:cancel",
|
|
5738
|
+
"opsx:rollback",
|
|
5739
|
+
"opsx:confirm",
|
|
5740
|
+
"opsx:next",
|
|
5741
|
+
"opsx:auto",
|
|
5742
|
+
"opsx:test"
|
|
5605
5743
|
];
|
|
5606
5744
|
builtInAgents = [
|
|
5607
5745
|
"frontend-dev",
|
|
@@ -5650,8 +5788,19 @@ var CommandParser = class {
|
|
|
5650
5788
|
if (!command) {
|
|
5651
5789
|
return { success: false, error: "\u65E0\u6548\u7684\u547D\u4EE4\u683C\u5F0F" };
|
|
5652
5790
|
}
|
|
5791
|
+
if (command.startsWith("opsx:")) {
|
|
5792
|
+
return {
|
|
5793
|
+
success: true,
|
|
5794
|
+
command: {
|
|
5795
|
+
type: "slash" /* SLASH */,
|
|
5796
|
+
raw: input,
|
|
5797
|
+
command,
|
|
5798
|
+
args
|
|
5799
|
+
}
|
|
5800
|
+
};
|
|
5801
|
+
}
|
|
5653
5802
|
const isValidCommand = this.slashCommands.some(
|
|
5654
|
-
(cmd) => cmd === command
|
|
5803
|
+
(cmd) => cmd === command
|
|
5655
5804
|
);
|
|
5656
5805
|
if (!isValidCommand) {
|
|
5657
5806
|
return { success: false, error: `\u672A\u77E5\u547D\u4EE4: /${command}` };
|
|
@@ -6769,10 +6918,15 @@ async function handleNew(args, ctx) {
|
|
|
6769
6918
|
}
|
|
6770
6919
|
}
|
|
6771
6920
|
return {
|
|
6772
|
-
output: chalk9__default.default.yellow("\u5F53\u524D\u5DF2\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.
|
|
6921
|
+
output: chalk9__default.default.yellow("\u5F53\u524D\u5DF2\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.white(`
|
|
6773
6922
|
|
|
6774
|
-
\
|
|
6775
|
-
\
|
|
6923
|
+
\u{1F4CB} ${existingState.title || existingState.id}`) + chalk9__default.default.gray(`
|
|
6924
|
+
\u7C7B\u578B: ${existingState.type} | \u590D\u6742\u5EA6: ${existingState.complexity}/10`) + chalk9__default.default.cyan(`
|
|
6925
|
+
|
|
6926
|
+
\u8FDB\u5EA6: ${existingState.steps.map((s) => {
|
|
6927
|
+
const icon = s.status === "completed" ? "\u2713" : s.status === "running" ? "\u25CF" : "\u25CB";
|
|
6928
|
+
return `${icon} ${s.step}`;
|
|
6929
|
+
}).join(" \u2192 ")}`) + chalk9__default.default.yellow("\n\n\u53EF\u7528\u547D\u4EE4:") + chalk9__default.default.white("\n /opsx:status - \u67E5\u770B\u5DE5\u4F5C\u6D41\u8BE6\u60C5") + chalk9__default.default.white("\n /opsx:cancel - \u53D6\u6D88\u5F53\u524D\u5DE5\u4F5C\u6D41")
|
|
6776
6930
|
};
|
|
6777
6931
|
}
|
|
6778
6932
|
}
|
|
@@ -7429,9 +7583,13 @@ async function handleOpsx(command, args, ctx) {
|
|
|
7429
7583
|
return handleAutoSchedule(args);
|
|
7430
7584
|
case "test":
|
|
7431
7585
|
return handleRegressionTest(ctx);
|
|
7586
|
+
case "list":
|
|
7587
|
+
return handleList(workflow);
|
|
7588
|
+
case "switch":
|
|
7589
|
+
return handleSwitch(workflow, args);
|
|
7432
7590
|
default:
|
|
7433
7591
|
return {
|
|
7434
|
-
output: chalk9__default.default.red(`\u672A\u77E5\u7684OpenSpec\u547D\u4EE4: /${command}`)
|
|
7592
|
+
output: chalk9__default.default.red(`\u672A\u77E5\u7684OpenSpec\u547D\u4EE4: /${command}`) + chalk9__default.default.gray("\n\u53EF\u7528\u547D\u4EE4: /opsx:list, /opsx:status, /opsx:confirm, /opsx:next, /opsx:archive")
|
|
7435
7593
|
};
|
|
7436
7594
|
}
|
|
7437
7595
|
}
|
|
@@ -7904,6 +8062,76 @@ ${generateConfirmationPrompt(e.point)}`) + chalk9__default.default.cyan(`
|
|
|
7904
8062
|
throw e;
|
|
7905
8063
|
}
|
|
7906
8064
|
}
|
|
8065
|
+
async function handleList(workflow, ctx) {
|
|
8066
|
+
const lines = [];
|
|
8067
|
+
const activeWorkflows = await workflow.getAllActiveWorkflows();
|
|
8068
|
+
const currentState = workflow.getState();
|
|
8069
|
+
if (activeWorkflows.length === 0) {
|
|
8070
|
+
return {
|
|
8071
|
+
output: chalk9__default.default.gray("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.yellow("\n\n\u4F7F\u7528 /new <\u9700\u6C42\u63CF\u8FF0> \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
|
|
8072
|
+
};
|
|
8073
|
+
}
|
|
8074
|
+
lines.push(chalk9__default.default.cyan.bold(`\u{1F4CB} \u6D3B\u8DC3\u5DE5\u4F5C\u6D41 (${activeWorkflows.length})`));
|
|
8075
|
+
lines.push("");
|
|
8076
|
+
for (const wf of activeWorkflows) {
|
|
8077
|
+
const isCurrent = currentState?.id === wf.id;
|
|
8078
|
+
const prefix = isCurrent ? chalk9__default.default.green("\u25B6 ") : " ";
|
|
8079
|
+
const title = isCurrent ? chalk9__default.default.white(wf.title) : chalk9__default.default.gray(wf.title);
|
|
8080
|
+
const stepIcon = wf.currentStep === "propose" || wf.currentStep === "explore" ? "\u23F3" : wf.currentStep === "apply" ? "\u{1F527}" : wf.currentStep === "archive" ? "\u{1F4E6}" : "\u{1F4DD}";
|
|
8081
|
+
lines.push(`${prefix}${title}`);
|
|
8082
|
+
lines.push(chalk9__default.default.gray(` ID: ${wf.id}`));
|
|
8083
|
+
lines.push(chalk9__default.default.gray(` \u9636\u6BB5: ${stepIcon} ${wf.currentStep} | \u590D\u6742\u5EA6: ${wf.complexity}/10`));
|
|
8084
|
+
if (isCurrent) {
|
|
8085
|
+
lines.push(chalk9__default.default.green(" (\u5F53\u524D)"));
|
|
8086
|
+
}
|
|
8087
|
+
lines.push("");
|
|
8088
|
+
}
|
|
8089
|
+
if (activeWorkflows.length > 1) {
|
|
8090
|
+
lines.push(chalk9__default.default.yellow("\u5207\u6362\u5DE5\u4F5C\u6D41:"));
|
|
8091
|
+
lines.push(chalk9__default.default.gray(" /opsx:switch <\u53D8\u66F4ID>"));
|
|
8092
|
+
}
|
|
8093
|
+
lines.push(chalk9__default.default.yellow("\n\u64CD\u4F5C\u547D\u4EE4:"));
|
|
8094
|
+
lines.push(chalk9__default.default.gray(" /opsx:status - \u67E5\u770B\u5F53\u524D\u5DE5\u4F5C\u6D41\u8BE6\u60C5"));
|
|
8095
|
+
lines.push(chalk9__default.default.gray(" /opsx:confirm - \u786E\u8BA4\u89C4\u683C"));
|
|
8096
|
+
lines.push(chalk9__default.default.gray(" /opsx:next - \u8FDB\u5165\u4E0B\u4E00\u9636\u6BB5"));
|
|
8097
|
+
lines.push(chalk9__default.default.gray(" /opsx:cancel - \u53D6\u6D88\u5F53\u524D\u5DE5\u4F5C\u6D41"));
|
|
8098
|
+
return { output: lines.join("\n") };
|
|
8099
|
+
}
|
|
8100
|
+
async function handleSwitch(workflow, args, ctx) {
|
|
8101
|
+
const targetId = args[0];
|
|
8102
|
+
if (!targetId) {
|
|
8103
|
+
const activeWorkflows = await workflow.getAllActiveWorkflows();
|
|
8104
|
+
if (activeWorkflows.length === 0) {
|
|
8105
|
+
return {
|
|
8106
|
+
output: chalk9__default.default.gray("\u6CA1\u6709\u53EF\u5207\u6362\u7684\u5DE5\u4F5C\u6D41")
|
|
8107
|
+
};
|
|
8108
|
+
}
|
|
8109
|
+
const lines = [
|
|
8110
|
+
chalk9__default.default.cyan("\u53EF\u7528\u5DE5\u4F5C\u6D41:"),
|
|
8111
|
+
""
|
|
8112
|
+
];
|
|
8113
|
+
for (const wf of activeWorkflows) {
|
|
8114
|
+
lines.push(chalk9__default.default.white(` ${wf.id}`) + chalk9__default.default.gray(` - ${wf.title.slice(0, 30)}...`));
|
|
8115
|
+
}
|
|
8116
|
+
lines.push("");
|
|
8117
|
+
lines.push(chalk9__default.default.gray("\u7528\u6CD5: /opsx:switch <\u53D8\u66F4ID>"));
|
|
8118
|
+
return { output: lines.join("\n") };
|
|
8119
|
+
}
|
|
8120
|
+
const success = await workflow.switchTo(targetId);
|
|
8121
|
+
if (success) {
|
|
8122
|
+
const state = workflow.getState();
|
|
8123
|
+
return {
|
|
8124
|
+
output: chalk9__default.default.green(`\u2713 \u5DF2\u5207\u6362\u5230\u5DE5\u4F5C\u6D41: ${targetId}`) + chalk9__default.default.gray(`
|
|
8125
|
+
|
|
8126
|
+
\u9700\u6C42: ${state?.title}`) + chalk9__default.default.cyan(`
|
|
8127
|
+
\u5F53\u524D\u9636\u6BB5: ${state?.currentStep}`) + chalk9__default.default.yellow("\n\n\u4F7F\u7528 /opsx:status \u67E5\u770B\u8BE6\u60C5")
|
|
8128
|
+
};
|
|
8129
|
+
} else {
|
|
8130
|
+
return {
|
|
8131
|
+
output: chalk9__default.default.red(`\u5207\u6362\u5931\u8D25: \u627E\u4E0D\u5230\u5DE5\u4F5C\u6D41 ${targetId}`) + chalk9__default.default.gray("\n\u4F7F\u7528 /opsx:list \u67E5\u770B\u6240\u6709\u6D3B\u8DC3\u5DE5\u4F5C\u6D41")
|
|
8132
|
+
};
|
|
8133
|
+
}
|
|
8134
|
+
}
|
|
7907
8135
|
|
|
7908
8136
|
// src/commands/runner.ts
|
|
7909
8137
|
function getVersion() {
|
|
@@ -8086,7 +8314,11 @@ var ALLOWED_COMMANDS_WITHOUT_WORKFLOW = [
|
|
|
8086
8314
|
"update",
|
|
8087
8315
|
"u",
|
|
8088
8316
|
"version",
|
|
8089
|
-
"v"
|
|
8317
|
+
"v",
|
|
8318
|
+
// OpenSpec 工作流管理命令(始终允许)
|
|
8319
|
+
"opsx:status",
|
|
8320
|
+
"opsx:cancel",
|
|
8321
|
+
"opsx:rollback"
|
|
8090
8322
|
];
|
|
8091
8323
|
var STAGE_PERMISSIONS = {
|
|
8092
8324
|
"explore": {
|
|
@@ -8159,6 +8391,12 @@ var CommandExecutor = class {
|
|
|
8159
8391
|
checkWorkflowPermission(command, ctx) {
|
|
8160
8392
|
const workflowEngine = ctx.workflowEngine;
|
|
8161
8393
|
const workflowState = workflowEngine?.getState();
|
|
8394
|
+
if (command.type === "slash" /* SLASH */) {
|
|
8395
|
+
const cmd = command.command?.toLowerCase();
|
|
8396
|
+
if (cmd?.startsWith("opsx:")) {
|
|
8397
|
+
return { allowed: true };
|
|
8398
|
+
}
|
|
8399
|
+
}
|
|
8162
8400
|
if (!workflowState) {
|
|
8163
8401
|
if (command.type === "slash" /* SLASH */) {
|
|
8164
8402
|
const cmd = command.command?.toLowerCase();
|