abelworkflow 0.6.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitignore +3 -1
- package/AGENTS.md +3 -3
- package/README.md +6 -6
- package/commands/{oc/diagnose.md → abel-diagnose.md} +6 -6
- package/commands/{oc/implementation.md → abel-implement.md} +5 -5
- package/commands/{oc/init.md → abel-init.md} +8 -8
- package/commands/{oc/plan.md → abel-plan.md} +7 -7
- package/commands/{oc/research.md → abel-research.md} +9 -9
- package/lib/cli/logic.mjs +99 -41
- package/lib/cli.mjs +538 -292
- package/package.json +7 -2
- package/skills/confidence-check/SKILL.md +20 -110
- package/skills/confidence-check/confidence.ts +1 -60
- package/skills/grok-search/.env.example +3 -3
- package/skills/grok-search/SKILL.md +1 -1
- package/skills/grok-search/scripts/groksearch_cli.py +1 -1
- package/skills/prompt-enhancer/.env.example +6 -8
- package/skills/prompt-enhancer/ADVANCED.md +14 -12
- package/skills/prompt-enhancer/SKILL.md +5 -1
- package/skills/prompt-enhancer/scripts/enhance.py +115 -76
- package/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py +47 -6
package/.gitignore
CHANGED
package/AGENTS.md
CHANGED
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
## Context Rules
|
|
15
15
|
|
|
16
|
-
-
|
|
16
|
+
- {{CODEBASE_RETRIEVAL_POLICY}}
|
|
17
17
|
- Rely only on project code plus `grok/context7` results
|
|
18
18
|
- If information is insufficient or uncertain, state it explicitly
|
|
19
19
|
|
|
20
20
|
## Workflow
|
|
21
21
|
|
|
22
22
|
```
|
|
23
|
-
/
|
|
24
|
-
|
|
23
|
+
/abel-init → /abel-research → /abel-plan → /abel-implement(TDD)
|
|
24
|
+
↘ /abel-diagnose (bug fix)
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## Universal Constraints
|
package/README.md
CHANGED
|
@@ -112,7 +112,7 @@ npx abelworkflow --help
|
|
|
112
112
|
|---|---|---|
|
|
113
113
|
| `grok-search` | `~/.agents/skills/grok-search/.env` | `GROK_API_URL` `GROK_API_KEY` `GROK_MODEL` |
|
|
114
114
|
| `context7-auto-research` | `~/.agents/skills/context7-auto-research/.env` | `CONTEXT7_API_KEY` |
|
|
115
|
-
| `prompt-enhancer` | `~/.agents/skills/prompt-enhancer/.env` | `
|
|
115
|
+
| `prompt-enhancer` | `~/.agents/skills/prompt-enhancer/.env` | `PE_API_URL` `PE_API_KEY` `PE_MODEL` |
|
|
116
116
|
|
|
117
117
|
### 方法二:源码克隆安装
|
|
118
118
|
|
|
@@ -178,15 +178,15 @@ node .\bin\abelworkflow.mjs install
|
|
|
178
178
|
|---|---|---|---|
|
|
179
179
|
| `AGENTS.md` | `~/.claude/CLAUDE.md` | `~/.codex/AGENTS.md` | 全局系统提示词/规则 |
|
|
180
180
|
| `skills/<skill>/` | `~/.claude/skills/<skill>/` | `~/.codex/skills/<skill>/` | Skills(每个目录一个技能) |
|
|
181
|
-
| `commands/
|
|
181
|
+
| `commands/abel-*.md` | `~/.claude/commands/abel-*.md` | `~/.codex/prompts/abel-*.md` | 扁平化部署,避免命名冲突 |
|
|
182
182
|
|
|
183
183
|
### 验证(可选)
|
|
184
184
|
|
|
185
185
|
**Linux/macOS(bash/zsh)**
|
|
186
186
|
|
|
187
187
|
```bash
|
|
188
|
-
ls -la "$HOME/.claude/CLAUDE.md" "$HOME/.claude/commands/
|
|
189
|
-
ls -la "$HOME/.codex/AGENTS.md" "$HOME/.codex/prompts/"
|
|
188
|
+
ls -la "$HOME/.claude/CLAUDE.md" "$HOME/.claude/commands/"abel-*.md
|
|
189
|
+
ls -la "$HOME/.codex/AGENTS.md" "$HOME/.codex/prompts/"abel-*.md
|
|
190
190
|
cat "$HOME/.claude/settings.json" | head
|
|
191
191
|
cat "$HOME/.codex/config.toml" | head
|
|
192
192
|
```
|
|
@@ -194,9 +194,9 @@ cat "$HOME/.codex/config.toml" | head
|
|
|
194
194
|
**Windows(PowerShell)**
|
|
195
195
|
|
|
196
196
|
```powershell
|
|
197
|
-
Get-Item "$HOME\.claude\CLAUDE.md"
|
|
197
|
+
Get-Item "$HOME\.claude\CLAUDE.md"; Get-ChildItem "$HOME\.claude\commands\abel-*.md"
|
|
198
198
|
Get-Item "$HOME\.codex\AGENTS.md"
|
|
199
|
-
Get-ChildItem "$HOME\.codex\prompts
|
|
199
|
+
Get-ChildItem "$HOME\.codex\prompts\abel-*.md"
|
|
200
200
|
Get-Content "$HOME\.claude\settings.json" -TotalCount 10
|
|
201
201
|
Get-Content "$HOME\.codex\config.toml" -TotalCount 10
|
|
202
202
|
```
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: abel-diagnose
|
|
3
3
|
description: Parallel diagnosis with batch fix reporting via systematic root cause analysis.
|
|
4
|
-
category:
|
|
5
|
-
tags: [diagnosis, bugfix]
|
|
4
|
+
category: abel
|
|
5
|
+
tags: [abel, diagnosis, bugfix]
|
|
6
6
|
argument-hint: <problem-description>
|
|
7
7
|
---
|
|
8
|
-
<!--
|
|
8
|
+
<!-- ABEL:START -->
|
|
9
9
|
**Arguments**
|
|
10
10
|
- Required: `<problem-description>` (one or more bug descriptions; comma-separated supported)
|
|
11
11
|
|
|
@@ -31,7 +31,7 @@ argument-hint: <problem-description>
|
|
|
31
31
|
|
|
32
32
|
**Steps**
|
|
33
33
|
1. Parse input, infer scope, and split into issue list (single or multiple).
|
|
34
|
-
2. For each issue in parallel: collect logs/traces and locate code via
|
|
34
|
+
2. For each issue in parallel: collect logs/traces and locate code via the configured codebase retrieval policy.
|
|
35
35
|
3. For each issue in parallel: perform root cause analysis; use `/sequential-think` for multi-component chains.
|
|
36
36
|
4. Build dependency/conflict graph across issues and compute safe fix order.
|
|
37
37
|
5. Run `/confidence-check` per issue; only issues with score ≥90% can move to fix generation.
|
|
@@ -60,4 +60,4 @@ Total: {n} | ReadyToFix: {n_ready} | Blocked: {n_blocked}
|
|
|
60
60
|
### Final Status
|
|
61
61
|
{FIXED|PARTIAL|NEEDS_REVIEW|BLOCKED}
|
|
62
62
|
```
|
|
63
|
-
<!--
|
|
63
|
+
<!-- ABEL:END -->
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: abel-implement
|
|
3
3
|
description: Implement approved changes with mandatory TDD.
|
|
4
|
-
category:
|
|
5
|
-
tags: [
|
|
4
|
+
category: abel
|
|
5
|
+
tags: [abel, implementation, TDD]
|
|
6
6
|
argument-hint: [change_name]
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
<!--
|
|
9
|
+
<!-- ABEL:START -->
|
|
10
10
|
**Arguments**
|
|
11
11
|
- Requested: `<change_name>`
|
|
12
12
|
|
|
@@ -154,4 +154,4 @@ Frontend Review
|
|
|
154
154
|
|
|
155
155
|
✓ Implementation complete
|
|
156
156
|
```
|
|
157
|
-
<!--
|
|
157
|
+
<!-- ABEL:END -->
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: abel-init
|
|
3
3
|
description: Initialize OpenSpec environment and validate required tooling.
|
|
4
|
-
category:
|
|
4
|
+
category: abel
|
|
5
5
|
tags: [openspec, init, setup]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
<!--
|
|
8
|
+
<!-- ABEL:START -->
|
|
9
9
|
**Guardrails**
|
|
10
10
|
- Complete steps in order; stop on failure
|
|
11
11
|
- Preserve existing config; do not overwrite without confirmation
|
|
@@ -16,12 +16,12 @@ tags: [openspec, init, setup]
|
|
|
16
16
|
2. Verify `openspec` availability via `openspec --version`.
|
|
17
17
|
3. If missing, `npm install -g @fission-ai/openspec@latest`, then re-check version.
|
|
18
18
|
4. Run `openspec init` (or `openspec update` for existing projects).
|
|
19
|
-
5.
|
|
20
|
-
|
|
19
|
+
5. {{AUGMENT_CONTEXT_ENGINE_VALIDATION}}
|
|
20
|
+
6. Verify required skills:
|
|
21
21
|
- Skills: `/dev-browser` `/sequential-think` `/context7-auto-research` `/grok-search` `/confidence-check`
|
|
22
|
-
|
|
22
|
+
7. Output summary with ✓/✗:
|
|
23
23
|
- OpenSpec installation
|
|
24
24
|
- Project initialization
|
|
25
|
-
- MCP availability
|
|
25
|
+
- MCP availability if enabled
|
|
26
26
|
- Required skills availability
|
|
27
|
-
<!--
|
|
27
|
+
<!-- ABEL:END -->
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: abel-plan
|
|
3
3
|
description: Refine approved change into a zero-decision executable plan.
|
|
4
|
-
category:
|
|
5
|
-
tags: [
|
|
4
|
+
category: abel
|
|
5
|
+
tags: [abel, plan, PBT]
|
|
6
6
|
argument-hint: [change_name]
|
|
7
7
|
---
|
|
8
|
-
<!--
|
|
8
|
+
<!-- ABEL:START -->
|
|
9
9
|
**Guardrails**
|
|
10
10
|
- Strictly adhere to **OpenSpec** rules when writing **standardized spec-structured projects**.
|
|
11
11
|
- The goal of this phase is to eliminate ALL decision points from the task flow—implementation should be pure mechanical execution.
|
|
@@ -39,8 +39,8 @@ argument-hint: [change_name]
|
|
|
39
39
|
|
|
40
40
|
4. **Uncertainty Elimination Audit**: Invoke skills to detect and eliminate remaining ambiguities:
|
|
41
41
|
```
|
|
42
|
-
# First,
|
|
43
|
-
|
|
42
|
+
# First, validate against existing codebase patterns
|
|
43
|
+
{{CODEBASE_RETRIEVAL_PATTERN_AUDIT}}
|
|
44
44
|
# Then audit for ambiguities directly and list them explicitly
|
|
45
45
|
Review change <change_name> for decision points that remain unspecified. For each: [AMBIGUITY] <description> → [REQUIRED CONSTRAINT] <what must be specified>.
|
|
46
46
|
Identify implicit assumptions in change <change_name>. For each: [ASSUMPTION] <description> → [EXPLICIT CONSTRAINT NEEDED] <concrete specification>.
|
|
@@ -85,4 +85,4 @@ A proposal is ready to exit the Plan phase only when:
|
|
|
85
85
|
- [ ] All PBT properties documented with falsification strategies
|
|
86
86
|
- [ ] `openspec validate <change_name> --strict` returns zero issues
|
|
87
87
|
- [ ] User has explicitly approved all constraint decisions
|
|
88
|
-
<!--
|
|
88
|
+
<!-- ABEL:END -->
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: abel-research
|
|
3
3
|
description: Transform user requirements into constraint sets via structured exploration (NO implementation)
|
|
4
|
-
category:
|
|
5
|
-
tags: [
|
|
4
|
+
category: abel
|
|
5
|
+
tags: [abel, research, constraints, exploration, subagents]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
<!--
|
|
8
|
+
<!-- ABEL:RESEARCH:START -->
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
# abel-research — Operating Mode (Constraints & Specs Only)
|
|
11
11
|
|
|
12
12
|
## Non‑Negotiable Rules (Highest Priority)
|
|
13
13
|
1. RESEARCH MODE ONLY.
|
|
@@ -38,7 +38,7 @@ Produce constraint sets that narrow the solution space, plus measurable success
|
|
|
38
38
|
---
|
|
39
39
|
|
|
40
40
|
## Phase 2 — Initial Codebase Assessment (Read‑Only)
|
|
41
|
-
-
|
|
41
|
+
- {{CODEBASE_RETRIEVAL_POLICY}}
|
|
42
42
|
- If technical research needed (architectural patterns, best practices), invoke `/grok-search` skill
|
|
43
43
|
- If the codebase spans multiple modules/directories, dispatch parallel explore subagents by context boundary.
|
|
44
44
|
|
|
@@ -73,7 +73,7 @@ All explore subagents MUST return valid JSON using this schema:
|
|
|
73
73
|
## Phase 5 — Parallel Subagent Dispatch
|
|
74
74
|
- Monitor subagent execution and collect structured reports.
|
|
75
75
|
- For each boundary, spawn an Explore subagent with:
|
|
76
|
-
-
|
|
76
|
+
- {{CODEBASE_RETRIEVAL_MANDATORY_RULE}}
|
|
77
77
|
- Clear scope
|
|
78
78
|
- self-contained with independent output
|
|
79
79
|
- Required output template (from Phase 4)
|
|
@@ -113,7 +113,7 @@ All explore subagents MUST return valid JSON using this schema:
|
|
|
113
113
|
|
|
114
114
|
## Reference
|
|
115
115
|
- Review existing constraints: `rg -n "Constraint:|MUST|MUST NOT" openspec/specs`
|
|
116
|
-
-
|
|
116
|
+
- {{CODEBASE_RETRIEVAL_STRUCTURE_REFERENCE}}
|
|
117
117
|
|
|
118
118
|
- Check prior research outputs: `ls openspec/changes/*/`
|
|
119
119
|
- OpenSpec CLI commands:
|
|
@@ -123,4 +123,4 @@ All explore subagents MUST return valid JSON using this schema:
|
|
|
123
123
|
- `openspec instructions proposal --change <name>` - Get proposal instructions
|
|
124
124
|
- Validate subagent outputs conform to template before aggregation.
|
|
125
125
|
- Ask the user directly for ANY ambiguity—do not assume or guess.
|
|
126
|
-
<!--
|
|
126
|
+
<!-- ABEL:RESEARCH:END -->
|
package/lib/cli/logic.mjs
CHANGED
|
@@ -1,23 +1,91 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
|
|
1
3
|
const interactiveMenuDescriptors = [
|
|
2
|
-
{ value: "full-init", label: "
|
|
3
|
-
{ value: "install", label: "
|
|
4
|
-
{ value: "grok-search", label: "配置 grok-search
|
|
5
|
-
{ value: "context7", label: "配置 context7-auto-research
|
|
6
|
-
{ value: "prompt-enhancer", label: "配置 prompt-enhancer
|
|
7
|
-
{ value: "claude-install", label: "
|
|
8
|
-
{ value: "claude-api", label: "配置 Claude
|
|
9
|
-
{ value: "codex-install", label: "
|
|
10
|
-
{ value: "codex-api", label: "配置 Codex
|
|
11
|
-
{ value: "exit", label: "退出" }
|
|
4
|
+
{ value: "full-init", label: "完整初始化", hint: "同步 + 安装 + 配置", group: "main" },
|
|
5
|
+
{ value: "install", label: "仅同步工作流", group: "main" },
|
|
6
|
+
{ value: "grok-search", label: "配置 grok-search", hint: "技能", group: "skill" },
|
|
7
|
+
{ value: "context7", label: "配置 context7-auto-research", hint: "技能", group: "skill" },
|
|
8
|
+
{ value: "prompt-enhancer", label: "配置 prompt-enhancer", hint: "技能", group: "skill" },
|
|
9
|
+
{ value: "claude-install", label: "安装/更新 Claude Code", hint: "CLI", group: "cli" },
|
|
10
|
+
{ value: "claude-api", label: "配置 Claude API", hint: "CLI", group: "cli" },
|
|
11
|
+
{ value: "codex-install", label: "安装/更新 Codex", hint: "CLI", group: "cli" },
|
|
12
|
+
{ value: "codex-api", label: "配置 Codex API", hint: "CLI", group: "cli" },
|
|
13
|
+
{ value: "exit", label: "退出", group: "exit" }
|
|
12
14
|
];
|
|
13
15
|
|
|
14
16
|
const interactiveMenuDefaultValue = "full-init";
|
|
15
17
|
|
|
18
|
+
class CancelledError extends Error {
|
|
19
|
+
constructor(message = "用户取消") {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "CancelledError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function required(message = "此项不能为空") {
|
|
26
|
+
return (value) => {
|
|
27
|
+
if (value === undefined || value === null || (typeof value === "string" && value.trim() === "")) {
|
|
28
|
+
return message;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function requiredUnlessExisting(existingValue, message = "此项不能为空") {
|
|
34
|
+
return (value) => {
|
|
35
|
+
if ((value === undefined || value === null || (typeof value === "string" && value.trim() === "")) && !existingValue) {
|
|
36
|
+
return message;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 回退逻辑:用户输入非空则用新值,否则用旧值。
|
|
43
|
+
* 输入 "-" 表示清除已有值(返回 undefined)。
|
|
44
|
+
* existingValue 可能来自 dotenv / JSON 读取,会传入空字符串;
|
|
45
|
+
* 空字符串将被净化为 undefined,避免写入无意义的空配置。
|
|
46
|
+
* 注意:本函数仅适用于字符串类型的配置值,不适用于可能为 0/false 的数字或布尔值。
|
|
47
|
+
*/
|
|
48
|
+
function resolvePasswordValue(userInput, existingValue) {
|
|
49
|
+
if (typeof userInput === "string") {
|
|
50
|
+
const trimmed = userInput.trim();
|
|
51
|
+
if (trimmed === "") {
|
|
52
|
+
if (typeof existingValue === "string" && existingValue.trim() === "") {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return existingValue || undefined;
|
|
56
|
+
}
|
|
57
|
+
return trimmed === "-" ? undefined : trimmed;
|
|
58
|
+
}
|
|
59
|
+
if (typeof existingValue === "string" && existingValue.trim() === "") {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
return existingValue || undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function assertNotCancelled(value) {
|
|
66
|
+
if (p.isCancel(value)) {
|
|
67
|
+
throw new CancelledError();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function confirmOrCancel({ message, initialValue = false }) {
|
|
72
|
+
const value = await p.confirm({ message, initialValue, active: "是", inactive: "否" });
|
|
73
|
+
assertNotCancelled(value);
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function selectOrCancel(options) {
|
|
78
|
+
const value = await p.select(options);
|
|
79
|
+
assertNotCancelled(value);
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
|
|
16
83
|
function parseArgs(argv, { defaultAgentsDir, resolvePath }) {
|
|
17
84
|
const options = {
|
|
18
85
|
agentsDir: defaultAgentsDir,
|
|
19
86
|
force: false,
|
|
20
87
|
relinkOnly: false,
|
|
88
|
+
nonInteractive: false,
|
|
21
89
|
command: "menu"
|
|
22
90
|
};
|
|
23
91
|
const positional = [];
|
|
@@ -42,6 +110,10 @@ function parseArgs(argv, { defaultAgentsDir, resolvePath }) {
|
|
|
42
110
|
i += 1;
|
|
43
111
|
continue;
|
|
44
112
|
}
|
|
113
|
+
if (arg === "--non-interactive") {
|
|
114
|
+
options.nonInteractive = true;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
45
117
|
if (arg === "--help" || arg === "-h" || arg === "help") {
|
|
46
118
|
helpRequested = true;
|
|
47
119
|
options.command = "help";
|
|
@@ -75,40 +147,22 @@ function parseArgs(argv, { defaultAgentsDir, resolvePath }) {
|
|
|
75
147
|
throw new Error("`--force`、`--link-only`、`--agents-dir` 仅能与 `install` 命令一起使用");
|
|
76
148
|
}
|
|
77
149
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
function assertInteractiveMenuSupported({ command, inputIsTTY, outputIsTTY }) {
|
|
82
|
-
if (command === "menu" && (!inputIsTTY || !outputIsTTY)) {
|
|
83
|
-
throw new Error("交互式菜单需要 TTY 终端;非交互场景请显式使用 `npx abelworkflow install`");
|
|
150
|
+
if (!options.nonInteractive && process.env.CI) {
|
|
151
|
+
options.nonInteractive = true;
|
|
84
152
|
}
|
|
85
|
-
}
|
|
86
153
|
|
|
87
|
-
|
|
88
|
-
const value = String(answer).trim();
|
|
89
|
-
if (!value && defaultValue !== undefined) {
|
|
90
|
-
return { ok: true, value: defaultValue };
|
|
91
|
-
}
|
|
92
|
-
if (!value && !allowEmpty) {
|
|
93
|
-
return { ok: false, error: "此项不能为空。" };
|
|
94
|
-
}
|
|
95
|
-
return { ok: true, value };
|
|
154
|
+
return options;
|
|
96
155
|
}
|
|
97
156
|
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
157
|
+
function assertInteractiveMenuSupported({ command, inputIsTTY, outputIsTTY, nonInteractive }) {
|
|
158
|
+
// 防御性检查(死代码守护):main() 已在调用前将非交互 menu 降级为 install,
|
|
159
|
+
// 此处仅防止外部直接调用 assertInteractiveMenuSupported 时漏掉判断。
|
|
160
|
+
if (command === "menu" && nonInteractive) {
|
|
161
|
+
throw new Error("非交互模式已启用;请显式使用 `npx abelworkflow install` 进行安装");
|
|
102
162
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return { ok: true, value: direct.value };
|
|
163
|
+
if (command === "menu" && (!inputIsTTY || !outputIsTTY)) {
|
|
164
|
+
throw new Error("交互式菜单需要 TTY 终端;非交互场景请显式使用 `npx abelworkflow install`");
|
|
106
165
|
}
|
|
107
|
-
return { ok: false, error: "无效选择,请重新输入。" };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function shouldUseVisibleSecretFallback({ inputIsTTY, platform }) {
|
|
111
|
-
return !inputIsTTY || platform === "win32";
|
|
112
166
|
}
|
|
113
167
|
|
|
114
168
|
function getRunCommandSpawnOptions(platform = process.env.ABELWORKFLOW_TEST_PLATFORM || process.platform) {
|
|
@@ -120,11 +174,15 @@ function getRunCommandSpawnOptions(platform = process.env.ABELWORKFLOW_TEST_PLAT
|
|
|
120
174
|
|
|
121
175
|
export {
|
|
122
176
|
assertInteractiveMenuSupported,
|
|
177
|
+
assertNotCancelled,
|
|
178
|
+
CancelledError,
|
|
179
|
+
confirmOrCancel,
|
|
123
180
|
getRunCommandSpawnOptions,
|
|
124
181
|
interactiveMenuDefaultValue,
|
|
125
182
|
interactiveMenuDescriptors,
|
|
126
183
|
parseArgs,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
184
|
+
required,
|
|
185
|
+
requiredUnlessExisting,
|
|
186
|
+
resolvePasswordValue,
|
|
187
|
+
selectOrCancel
|
|
130
188
|
};
|