abelworkflow 0.6.3 → 0.6.5
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 +1 -0
- package/commands/oc/plan.md +1 -1
- package/commands/oc/research.md +4 -4
- package/lib/cli/logic.mjs +130 -0
- package/lib/cli.mjs +60 -175
- package/lib/templates/codex/config-base.toml +1 -1
- package/package.json +4 -1
package/.gitignore
CHANGED
package/commands/oc/plan.md
CHANGED
|
@@ -77,7 +77,7 @@ argument-hint: [change_name]
|
|
|
77
77
|
- Use `openspec list --specs` to check for conflicts with existing specifications.
|
|
78
78
|
- Search existing patterns with `rg -n "INVARIANT:|PROPERTY:|Constraint:" openspec/` before defining new ones.
|
|
79
79
|
- For complex proposals, consider running steps 2-4 iteratively on sub-components.
|
|
80
|
-
-
|
|
80
|
+
- Ask the user directly for ANY ambiguity—do not assume or guess.
|
|
81
81
|
|
|
82
82
|
**Exit Criteria**
|
|
83
83
|
A proposal is ready to exit the Plan phase only when:
|
package/commands/oc/research.md
CHANGED
|
@@ -26,7 +26,7 @@ Produce constraint sets that narrow the solution space, plus measurable success
|
|
|
26
26
|
|
|
27
27
|
## Phase 0 — Requirement Intake Gate (MANDATORY)
|
|
28
28
|
- **MUST** confirm the user’s requirement exists and is clear **before** any research/action.
|
|
29
|
-
- If missing/unclear, **MUST**
|
|
29
|
+
- If missing/unclear, **MUST** ask the user directly in a concise grouped message to collect: goal, in-scope area, top scenarios, non-goals, known constraints, success signals.
|
|
30
30
|
- **MUST NOT** run `/opsx:new`, any codebase retrieval, spawn subagents, or generate artifacts until the user confirms a brief requirement summary.
|
|
31
31
|
|
|
32
32
|
---
|
|
@@ -97,7 +97,7 @@ All explore subagents MUST return valid JSON using this schema:
|
|
|
97
97
|
|
|
98
98
|
## Phase 7 — User Interaction for Ambiguity Resolution
|
|
99
99
|
- Compile prioritized list of open questions from aggregated reports.
|
|
100
|
-
-
|
|
100
|
+
- Present questions directly to the user in a concise grouped message:
|
|
101
101
|
* Group related questions together.
|
|
102
102
|
* Provide context for each question.
|
|
103
103
|
* Suggest default answers when applicable.
|
|
@@ -122,5 +122,5 @@ All explore subagents MUST return valid JSON using this schema:
|
|
|
122
122
|
- `openspec status --change <name>` - Check artifact completion status
|
|
123
123
|
- `openspec instructions proposal --change <name>` - Get proposal instructions
|
|
124
124
|
- Validate subagent outputs conform to template before aggregation.
|
|
125
|
-
-
|
|
126
|
-
<!-- OC:RESEARCH:END -->
|
|
125
|
+
- Ask the user directly for ANY ambiguity—do not assume or guess.
|
|
126
|
+
<!-- OC:RESEARCH:END -->
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const interactiveMenuDescriptors = [
|
|
2
|
+
{ value: "full-init", label: "完整初始化:同步工作流 + 可选安装/配置 Claude Code、Codex、技能环境" },
|
|
3
|
+
{ value: "install", label: "仅同步/更新工作流到 ~/.agents 并重新链接 Claude/Codex" },
|
|
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: "安装或更新 Claude Code CLI" },
|
|
8
|
+
{ value: "claude-api", label: "配置 Claude Code 第三方 API" },
|
|
9
|
+
{ value: "codex-install", label: "安装或更新 Codex CLI" },
|
|
10
|
+
{ value: "codex-api", label: "配置 Codex 第三方 API" },
|
|
11
|
+
{ value: "exit", label: "退出" }
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const interactiveMenuDefaultValue = "full-init";
|
|
15
|
+
|
|
16
|
+
function parseArgs(argv, { defaultAgentsDir, resolvePath }) {
|
|
17
|
+
const options = {
|
|
18
|
+
agentsDir: defaultAgentsDir,
|
|
19
|
+
force: false,
|
|
20
|
+
relinkOnly: false,
|
|
21
|
+
command: "menu"
|
|
22
|
+
};
|
|
23
|
+
const positional = [];
|
|
24
|
+
let helpRequested = false;
|
|
25
|
+
|
|
26
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
27
|
+
const arg = argv[i];
|
|
28
|
+
if (arg === "--force" || arg === "-f") {
|
|
29
|
+
options.force = true;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (arg === "--link-only") {
|
|
33
|
+
options.relinkOnly = true;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (arg === "--agents-dir") {
|
|
37
|
+
const value = argv[i + 1];
|
|
38
|
+
if (!value) {
|
|
39
|
+
throw new Error("--agents-dir requires a path");
|
|
40
|
+
}
|
|
41
|
+
options.agentsDir = resolvePath(value);
|
|
42
|
+
i += 1;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (arg === "--help" || arg === "-h" || arg === "help") {
|
|
46
|
+
helpRequested = true;
|
|
47
|
+
options.command = "help";
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (arg.startsWith("-")) {
|
|
51
|
+
throw new Error(`Unknown argument: ${arg}`);
|
|
52
|
+
}
|
|
53
|
+
positional.push(arg);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (positional.length > 1) {
|
|
57
|
+
throw new Error(`Unknown argument: ${positional.slice(1).join(" ")}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (positional[0]) {
|
|
61
|
+
if (["menu", "init"].includes(positional[0])) {
|
|
62
|
+
if (!helpRequested) {
|
|
63
|
+
options.command = "menu";
|
|
64
|
+
}
|
|
65
|
+
} else if (["install", "sync"].includes(positional[0])) {
|
|
66
|
+
if (!helpRequested) {
|
|
67
|
+
options.command = "install";
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
throw new Error(`Unknown command: ${positional[0]}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (options.command !== "install" && (options.force || options.relinkOnly || options.agentsDir !== defaultAgentsDir)) {
|
|
75
|
+
throw new Error("`--force`、`--link-only`、`--agents-dir` 仅能与 `install` 命令一起使用");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return options;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function assertInteractiveMenuSupported({ command, inputIsTTY, outputIsTTY }) {
|
|
82
|
+
if (command === "menu" && (!inputIsTTY || !outputIsTTY)) {
|
|
83
|
+
throw new Error("交互式菜单需要 TTY 终端;非交互场景请显式使用 `npx abelworkflow install`");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function resolvePromptValue(answer, { defaultValue, allowEmpty = false } = {}) {
|
|
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 };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function resolveSelectValue(answer, choices) {
|
|
99
|
+
const index = Number(answer) - 1;
|
|
100
|
+
if (Number.isInteger(index) && index >= 0 && index < choices.length) {
|
|
101
|
+
return { ok: true, value: choices[index].value };
|
|
102
|
+
}
|
|
103
|
+
const direct = choices.find((choice) => choice.value === answer);
|
|
104
|
+
if (direct) {
|
|
105
|
+
return { ok: true, value: direct.value };
|
|
106
|
+
}
|
|
107
|
+
return { ok: false, error: "无效选择,请重新输入。" };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function shouldUseVisibleSecretFallback({ inputIsTTY, platform }) {
|
|
111
|
+
return !inputIsTTY || platform === "win32";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function getRunCommandSpawnOptions(platform = process.env.ABELWORKFLOW_TEST_PLATFORM || process.platform) {
|
|
115
|
+
return {
|
|
116
|
+
stdio: "inherit",
|
|
117
|
+
shell: platform === "win32"
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
assertInteractiveMenuSupported,
|
|
123
|
+
getRunCommandSpawnOptions,
|
|
124
|
+
interactiveMenuDefaultValue,
|
|
125
|
+
interactiveMenuDescriptors,
|
|
126
|
+
parseArgs,
|
|
127
|
+
resolvePromptValue,
|
|
128
|
+
resolveSelectValue,
|
|
129
|
+
shouldUseVisibleSecretFallback
|
|
130
|
+
};
|
package/lib/cli.mjs
CHANGED
|
@@ -5,6 +5,16 @@ import { dirname, join, relative, resolve } from "node:path";
|
|
|
5
5
|
import { stdin as input, stdout as output } from "node:process";
|
|
6
6
|
import { createInterface } from "node:readline/promises";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
+
import {
|
|
9
|
+
assertInteractiveMenuSupported,
|
|
10
|
+
getRunCommandSpawnOptions,
|
|
11
|
+
interactiveMenuDefaultValue,
|
|
12
|
+
interactiveMenuDescriptors,
|
|
13
|
+
parseArgs,
|
|
14
|
+
resolvePromptValue,
|
|
15
|
+
resolveSelectValue,
|
|
16
|
+
shouldUseVisibleSecretFallback
|
|
17
|
+
} from "./cli/logic.mjs";
|
|
8
18
|
|
|
9
19
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
20
|
const packageRoot = dirname(dirname(__filename));
|
|
@@ -87,83 +97,6 @@ const ignoredSkillPathPatterns = [
|
|
|
87
97
|
/^dev-browser\/profiles(\/|$)/,
|
|
88
98
|
/^dev-browser\/tmp(\/|$)/
|
|
89
99
|
];
|
|
90
|
-
const menuChoices = [
|
|
91
|
-
{ value: "full-init", label: "完整初始化:同步工作流 + 可选安装/配置 Claude Code、Codex、技能环境" },
|
|
92
|
-
{ value: "install", label: "仅同步/更新工作流到 ~/.agents 并重新链接 Claude/Codex" },
|
|
93
|
-
{ value: "grok-search", label: "配置 grok-search 环境变量" },
|
|
94
|
-
{ value: "context7", label: "配置 context7-auto-research 环境变量" },
|
|
95
|
-
{ value: "prompt-enhancer", label: "配置 prompt-enhancer 环境变量" },
|
|
96
|
-
{ value: "claude-install", label: "安装或更新 Claude Code CLI" },
|
|
97
|
-
{ value: "claude-api", label: "配置 Claude Code 第三方 API" },
|
|
98
|
-
{ value: "codex-install", label: "安装或更新 Codex CLI" },
|
|
99
|
-
{ value: "codex-api", label: "配置 Codex 第三方 API" },
|
|
100
|
-
{ value: "exit", label: "退出" }
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
function parseArgs(argv) {
|
|
104
|
-
const options = {
|
|
105
|
-
agentsDir: defaultAgentsDir,
|
|
106
|
-
force: false,
|
|
107
|
-
relinkOnly: false,
|
|
108
|
-
command: "menu"
|
|
109
|
-
};
|
|
110
|
-
const positional = [];
|
|
111
|
-
let helpRequested = false;
|
|
112
|
-
|
|
113
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
114
|
-
const arg = argv[i];
|
|
115
|
-
if (arg === "--force" || arg === "-f") {
|
|
116
|
-
options.force = true;
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
if (arg === "--link-only") {
|
|
120
|
-
options.relinkOnly = true;
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (arg === "--agents-dir") {
|
|
124
|
-
const value = argv[i + 1];
|
|
125
|
-
if (!value) {
|
|
126
|
-
throw new Error("--agents-dir requires a path");
|
|
127
|
-
}
|
|
128
|
-
options.agentsDir = resolve(value);
|
|
129
|
-
i += 1;
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (arg === "--help" || arg === "-h" || arg === "help") {
|
|
133
|
-
helpRequested = true;
|
|
134
|
-
options.command = "help";
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
if (arg.startsWith("-")) {
|
|
138
|
-
throw new Error(`Unknown argument: ${arg}`);
|
|
139
|
-
}
|
|
140
|
-
positional.push(arg);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (positional.length > 1) {
|
|
144
|
-
throw new Error(`Unknown argument: ${positional.slice(1).join(" ")}`);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (positional[0]) {
|
|
148
|
-
if (["menu", "init"].includes(positional[0])) {
|
|
149
|
-
if (!helpRequested) {
|
|
150
|
-
options.command = "menu";
|
|
151
|
-
}
|
|
152
|
-
} else if (["install", "sync"].includes(positional[0])) {
|
|
153
|
-
if (!helpRequested) {
|
|
154
|
-
options.command = "install";
|
|
155
|
-
}
|
|
156
|
-
} else {
|
|
157
|
-
throw new Error(`Unknown command: ${positional[0]}`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (options.command === "menu" && (options.force || options.relinkOnly || options.agentsDir !== defaultAgentsDir)) {
|
|
162
|
-
throw new Error("`--force`、`--link-only`、`--agents-dir` 仅能与 `install` 命令一起使用");
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return options;
|
|
166
|
-
}
|
|
167
100
|
|
|
168
101
|
function printHelp() {
|
|
169
102
|
console.log(`AbelWorkflow installer
|
|
@@ -982,22 +915,18 @@ async function promptText(message, options = {}) {
|
|
|
982
915
|
rl.close();
|
|
983
916
|
}
|
|
984
917
|
|
|
985
|
-
const
|
|
986
|
-
if (
|
|
987
|
-
return
|
|
988
|
-
}
|
|
989
|
-
if (!value && !allowEmpty) {
|
|
990
|
-
console.log("此项不能为空。");
|
|
991
|
-
continue;
|
|
918
|
+
const resolved = resolvePromptValue(answer, { defaultValue, allowEmpty });
|
|
919
|
+
if (resolved.ok) {
|
|
920
|
+
return resolved.value;
|
|
992
921
|
}
|
|
993
|
-
|
|
922
|
+
console.log(resolved.error);
|
|
994
923
|
}
|
|
995
924
|
}
|
|
996
925
|
|
|
997
926
|
async function promptSecret(message, options = {}) {
|
|
998
927
|
const { defaultValue, allowEmpty = false } = options;
|
|
999
928
|
|
|
1000
|
-
if (
|
|
929
|
+
if (shouldUseVisibleSecretFallback({ inputIsTTY: input.isTTY, platform: getPlatform() })) {
|
|
1001
930
|
while (true) {
|
|
1002
931
|
const suffix = defaultValue !== undefined && defaultValue !== ""
|
|
1003
932
|
? " [直接回车保留现有值]"
|
|
@@ -1010,15 +939,11 @@ async function promptSecret(message, options = {}) {
|
|
|
1010
939
|
rl.close();
|
|
1011
940
|
}
|
|
1012
941
|
|
|
1013
|
-
const
|
|
1014
|
-
if (
|
|
1015
|
-
return
|
|
1016
|
-
}
|
|
1017
|
-
if (!value && !allowEmpty) {
|
|
1018
|
-
console.log("此项不能为空。");
|
|
1019
|
-
continue;
|
|
942
|
+
const resolved = resolvePromptValue(answer, { defaultValue, allowEmpty });
|
|
943
|
+
if (resolved.ok) {
|
|
944
|
+
return resolved.value;
|
|
1020
945
|
}
|
|
1021
|
-
|
|
946
|
+
console.log(resolved.error);
|
|
1022
947
|
}
|
|
1023
948
|
}
|
|
1024
949
|
|
|
@@ -1037,15 +962,11 @@ async function promptSecret(message, options = {}) {
|
|
|
1037
962
|
rl.close();
|
|
1038
963
|
}
|
|
1039
964
|
|
|
1040
|
-
const
|
|
1041
|
-
if (
|
|
1042
|
-
return
|
|
965
|
+
const resolved = resolvePromptValue(answer, { defaultValue, allowEmpty });
|
|
966
|
+
if (resolved.ok) {
|
|
967
|
+
return resolved.value;
|
|
1043
968
|
}
|
|
1044
|
-
|
|
1045
|
-
console.log("此项不能为空。");
|
|
1046
|
-
continue;
|
|
1047
|
-
}
|
|
1048
|
-
return value;
|
|
969
|
+
console.log(resolved.error);
|
|
1049
970
|
}
|
|
1050
971
|
}
|
|
1051
972
|
|
|
@@ -1060,15 +981,11 @@ async function promptSelect(message, choices, options = {}) {
|
|
|
1060
981
|
while (true) {
|
|
1061
982
|
const fallbackValue = defaultIndex >= 0 ? String(defaultIndex + 1) : undefined;
|
|
1062
983
|
const answer = await promptText("请输入序号", { defaultValue: fallbackValue, allowEmpty: defaultIndex >= 0 });
|
|
1063
|
-
const
|
|
1064
|
-
if (
|
|
1065
|
-
return
|
|
984
|
+
const resolved = resolveSelectValue(answer, choices);
|
|
985
|
+
if (resolved.ok) {
|
|
986
|
+
return resolved.value;
|
|
1066
987
|
}
|
|
1067
|
-
|
|
1068
|
-
if (direct) {
|
|
1069
|
-
return direct.value;
|
|
1070
|
-
}
|
|
1071
|
-
console.log("无效选择,请重新输入。");
|
|
988
|
+
console.log(resolved.error);
|
|
1072
989
|
}
|
|
1073
990
|
}
|
|
1074
991
|
|
|
@@ -1086,16 +1003,9 @@ function commandExists(command) {
|
|
|
1086
1003
|
return result.status === 0;
|
|
1087
1004
|
}
|
|
1088
1005
|
|
|
1089
|
-
function getRunCommandSpawnOptions(platform = getPlatform()) {
|
|
1090
|
-
return {
|
|
1091
|
-
stdio: "inherit",
|
|
1092
|
-
shell: platform === "win32"
|
|
1093
|
-
};
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
1006
|
async function runCommand(command, args) {
|
|
1097
1007
|
await new Promise((resolvePromise, rejectPromise) => {
|
|
1098
|
-
const child = spawn(command, args, getRunCommandSpawnOptions());
|
|
1008
|
+
const child = spawn(command, args, getRunCommandSpawnOptions(getPlatform()));
|
|
1099
1009
|
child.on("error", rejectPromise);
|
|
1100
1010
|
child.on("close", (code) => {
|
|
1101
1011
|
if (code === 0) {
|
|
@@ -1871,8 +1781,8 @@ function buildCodexConfigContent(currentContent, {
|
|
|
1871
1781
|
content = mergeCodexTemplateDefaults(content, effectiveTemplateContent);
|
|
1872
1782
|
}
|
|
1873
1783
|
const lineEnding = detectLineEnding(content);
|
|
1874
|
-
if (includeSubagentDefaults && readTopLevelTomlString(content, "approvals_reviewer") === "
|
|
1875
|
-
content = updateTopLevelTomlField(content, "approvals_reviewer", "
|
|
1784
|
+
if (includeSubagentDefaults && readTopLevelTomlString(content, "approvals_reviewer") === "reviewer") {
|
|
1785
|
+
content = updateTopLevelTomlField(content, "approvals_reviewer", "guardian_subagent");
|
|
1876
1786
|
}
|
|
1877
1787
|
content = updateTopLevelTomlField(content, "model_provider", providerId);
|
|
1878
1788
|
content = updateTopLevelTomlField(content, "preferred_auth_method", "apikey");
|
|
@@ -1965,57 +1875,39 @@ async function runInteractiveMenu(options) {
|
|
|
1965
1875
|
console.log("AbelWorkflow Setup");
|
|
1966
1876
|
console.log(`工作流目录: ${pathToLabel(options.agentsDir)}`);
|
|
1967
1877
|
|
|
1968
|
-
|
|
1969
|
-
|
|
1878
|
+
const menuChoices = interactiveMenuDescriptors.map(({ value, label }) => ({ value, label }));
|
|
1879
|
+
const menuActions = {
|
|
1880
|
+
"full-init": async () => runFullInit(options),
|
|
1881
|
+
install: async () => installManagedWorkflow({
|
|
1882
|
+
agentsDir: options.agentsDir,
|
|
1883
|
+
force: options.force,
|
|
1884
|
+
relinkOnly: options.relinkOnly
|
|
1885
|
+
}),
|
|
1886
|
+
"grok-search": async () => configureGrokSearchEnv(options.agentsDir),
|
|
1887
|
+
context7: async () => configureContext7Env(options.agentsDir),
|
|
1888
|
+
"prompt-enhancer": async () => configurePromptEnhancerEnv(options.agentsDir),
|
|
1889
|
+
"claude-install": async () => installCliTool("claude"),
|
|
1890
|
+
"claude-api": async () => configureClaudeApi(),
|
|
1891
|
+
"codex-install": async () => installCliTool("codex"),
|
|
1892
|
+
"codex-api": async () => configureCodexApi()
|
|
1893
|
+
};
|
|
1970
1894
|
|
|
1971
|
-
|
|
1895
|
+
while (true) {
|
|
1896
|
+
const choice = await promptSelect("请选择操作", menuChoices, { defaultValue: interactiveMenuDefaultValue });
|
|
1897
|
+
const descriptor = interactiveMenuDescriptors.find((item) => item.value === choice);
|
|
1898
|
+
if (descriptor?.value === "exit") {
|
|
1972
1899
|
return;
|
|
1973
1900
|
}
|
|
1974
1901
|
|
|
1975
|
-
|
|
1976
|
-
await runFullInit(options);
|
|
1977
|
-
continue;
|
|
1978
|
-
}
|
|
1979
|
-
if (choice === "install") {
|
|
1980
|
-
await installManagedWorkflow({
|
|
1981
|
-
agentsDir: options.agentsDir,
|
|
1982
|
-
force: options.force,
|
|
1983
|
-
relinkOnly: options.relinkOnly
|
|
1984
|
-
});
|
|
1985
|
-
continue;
|
|
1986
|
-
}
|
|
1987
|
-
if (choice === "grok-search") {
|
|
1988
|
-
await configureGrokSearchEnv(options.agentsDir);
|
|
1989
|
-
continue;
|
|
1990
|
-
}
|
|
1991
|
-
if (choice === "context7") {
|
|
1992
|
-
await configureContext7Env(options.agentsDir);
|
|
1993
|
-
continue;
|
|
1994
|
-
}
|
|
1995
|
-
if (choice === "prompt-enhancer") {
|
|
1996
|
-
await configurePromptEnhancerEnv(options.agentsDir);
|
|
1997
|
-
continue;
|
|
1998
|
-
}
|
|
1999
|
-
if (choice === "claude-install") {
|
|
2000
|
-
await installCliTool("claude");
|
|
2001
|
-
continue;
|
|
2002
|
-
}
|
|
2003
|
-
if (choice === "claude-api") {
|
|
2004
|
-
await configureClaudeApi();
|
|
2005
|
-
continue;
|
|
2006
|
-
}
|
|
2007
|
-
if (choice === "codex-install") {
|
|
2008
|
-
await installCliTool("codex");
|
|
2009
|
-
continue;
|
|
2010
|
-
}
|
|
2011
|
-
if (choice === "codex-api") {
|
|
2012
|
-
await configureCodexApi();
|
|
2013
|
-
}
|
|
1902
|
+
await menuActions[descriptor.value]();
|
|
2014
1903
|
}
|
|
2015
1904
|
}
|
|
2016
1905
|
|
|
2017
1906
|
async function main() {
|
|
2018
|
-
const options = parseArgs(process.argv.slice(2)
|
|
1907
|
+
const options = parseArgs(process.argv.slice(2), {
|
|
1908
|
+
defaultAgentsDir,
|
|
1909
|
+
resolvePath: resolve
|
|
1910
|
+
});
|
|
2019
1911
|
|
|
2020
1912
|
if (options.command === "help") {
|
|
2021
1913
|
printHelp();
|
|
@@ -2027,9 +1919,11 @@ async function main() {
|
|
|
2027
1919
|
return;
|
|
2028
1920
|
}
|
|
2029
1921
|
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
1922
|
+
assertInteractiveMenuSupported({
|
|
1923
|
+
command: options.command,
|
|
1924
|
+
inputIsTTY: input.isTTY,
|
|
1925
|
+
outputIsTTY: output.isTTY
|
|
1926
|
+
});
|
|
2033
1927
|
|
|
2034
1928
|
await runInteractiveMenu(options);
|
|
2035
1929
|
}
|
|
@@ -2043,12 +1937,3 @@ export {
|
|
|
2043
1937
|
resolveExistingCodexApiConfig,
|
|
2044
1938
|
updateTomlSectionFields
|
|
2045
1939
|
};
|
|
2046
|
-
|
|
2047
|
-
const isDirectExecution = process.argv[1] ? resolve(process.argv[1]) === __filename : false;
|
|
2048
|
-
|
|
2049
|
-
if (isDirectExecution) {
|
|
2050
|
-
main().catch((error) => {
|
|
2051
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
2052
|
-
process.exit(1);
|
|
2053
|
-
});
|
|
2054
|
-
}
|
|
@@ -2,7 +2,7 @@ personality = "pragmatic"
|
|
|
2
2
|
model_provider = "abelworkflow"
|
|
3
3
|
disable_response_storage = true
|
|
4
4
|
preferred_auth_method = "apikey"
|
|
5
|
-
approvals_reviewer = "
|
|
5
|
+
approvals_reviewer = "guardian_subagent"
|
|
6
6
|
approval_policy = "on-request"
|
|
7
7
|
sandbox_mode = "workspace-write"
|
|
8
8
|
service_tier = "fast"
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abelworkflow",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "Install AbelWorkflow into ~/.agents and create Claude/Codex symlinks.",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test:contracts": "node --test test/runtime-doc-contracts.test.mjs test/cli-contracts.test.mjs"
|
|
8
|
+
},
|
|
6
9
|
"bin": {
|
|
7
10
|
"abelworkflow": "bin/abelworkflow.mjs"
|
|
8
11
|
},
|