abelworkflow 1.0.0-rc.1 → 1.0.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/README.md +7 -8
- package/extensions/pi-gpt-responses-compat/index.ts +1 -1
- package/lib/cli/args.mjs +2 -2
- package/lib/cli/main.mjs +39 -41
- package/lib/cli/prompts.mjs +16 -29
- package/lib/installer/assets.mjs +13 -15
- package/lib/installer/install.mjs +18 -32
- package/lib/installer/state.mjs +0 -19
- package/lib/providers/claude.mjs +23 -214
- package/lib/providers/codex.mjs +7 -7
- package/lib/providers/pi.mjs +273 -58
- package/lib/providers/skills.mjs +29 -88
- package/lib/templates/workflow/AGENTS.md +10 -10
- package/lib/templates/workflow/commands/abel-design.md +175 -0
- package/lib/templates/workflow/commands/abel-implement.md +64 -46
- package/lib/templates/workflow/commands/abel-init.md +2 -4
- package/package.json +1 -7
- package/skills/grok-search/.env.example +3 -3
- package/skills/grok-search/SKILL.md +1 -1
- package/skills/grok-search/defaults.json +1 -1
- package/skills/prompt-enhancer/SKILL.md +2 -27
- package/lib/installer/render.mjs +0 -46
- package/lib/templates/workflow/commands/abel-plan.md +0 -82
- package/lib/templates/workflow/commands/abel-research.md +0 -126
- package/skills/prompt-enhancer/.env.example +0 -12
- package/skills/prompt-enhancer/ADVANCED.md +0 -103
- package/skills/prompt-enhancer/requirements.txt +0 -1
- package/skills/prompt-enhancer/scripts/_dotenv.py +0 -32
- package/skills/prompt-enhancer/scripts/enhance.py +0 -144
- package/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py +0 -238
package/lib/providers/claude.mjs
CHANGED
|
@@ -1,30 +1,10 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import {
|
|
3
|
-
pathExists,
|
|
4
3
|
readJsonFileSafe,
|
|
5
4
|
writeJsonFileWithBackup
|
|
6
5
|
} from "../config/store.mjs";
|
|
7
6
|
import { defaultPaths, maskSecret, pathToLabel } from "../paths.mjs";
|
|
8
7
|
|
|
9
|
-
const augmentContextEnginePermission = "mcp__augment-context-engine";
|
|
10
|
-
const claudePermissionProfiles = ["standard", "trusted"];
|
|
11
|
-
const trustedClaudePermissions = [
|
|
12
|
-
"Bash",
|
|
13
|
-
"Skill",
|
|
14
|
-
"LS",
|
|
15
|
-
"Read",
|
|
16
|
-
"Agent",
|
|
17
|
-
"Write",
|
|
18
|
-
"Edit",
|
|
19
|
-
"MultiEdit",
|
|
20
|
-
"Glob",
|
|
21
|
-
"Grep",
|
|
22
|
-
"WebFetch",
|
|
23
|
-
"WebSearch",
|
|
24
|
-
"TodoWrite",
|
|
25
|
-
"NotebookRead",
|
|
26
|
-
"NotebookEdit"
|
|
27
|
-
];
|
|
28
8
|
const claudeModelEnvKeys = [
|
|
29
9
|
"ANTHROPIC_MODEL",
|
|
30
10
|
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
@@ -37,47 +17,32 @@ const defaultClaudeSettings = {
|
|
|
37
17
|
env: {
|
|
38
18
|
DISABLE_TELEMETRY: "1",
|
|
39
19
|
DISABLE_ERROR_REPORTING: "1",
|
|
40
|
-
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1"
|
|
41
|
-
ANTHROPIC_BASE_URL: "",
|
|
42
|
-
ANTHROPIC_API_KEY: "",
|
|
43
|
-
ANTHROPIC_MODEL: "",
|
|
44
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL: "",
|
|
45
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL: "",
|
|
46
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL: "",
|
|
47
|
-
CLAUDE_CODE_SUBAGENT_MODEL: ""
|
|
20
|
+
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1"
|
|
48
21
|
},
|
|
49
22
|
includeCoAuthoredBy: false,
|
|
50
23
|
permissions: {
|
|
51
24
|
allow: [],
|
|
52
|
-
deny: []
|
|
25
|
+
deny: [],
|
|
26
|
+
defaultMode: "bypassPermissions"
|
|
53
27
|
},
|
|
54
28
|
hooks: {},
|
|
55
29
|
alwaysThinkingEnabled: true,
|
|
56
30
|
language: "Chinese"
|
|
57
31
|
};
|
|
58
|
-
function buildDefaultClaudeSettings(
|
|
59
|
-
|
|
60
|
-
throw new Error(`Unknown Claude permission profile: ${profile}`);
|
|
61
|
-
}
|
|
62
|
-
const settings = {
|
|
32
|
+
function buildDefaultClaudeSettings() {
|
|
33
|
+
return {
|
|
63
34
|
...defaultClaudeSettings,
|
|
64
35
|
env: { ...defaultClaudeSettings.env },
|
|
65
36
|
permissions: {
|
|
66
37
|
...defaultClaudeSettings.permissions,
|
|
67
|
-
allow:
|
|
38
|
+
allow: [...defaultClaudeSettings.permissions.allow],
|
|
68
39
|
deny: [...defaultClaudeSettings.permissions.deny]
|
|
69
40
|
},
|
|
70
41
|
hooks: { ...defaultClaudeSettings.hooks }
|
|
71
42
|
};
|
|
72
|
-
|
|
73
|
-
if (augmentContextEngine && !settings.permissions.allow.includes(augmentContextEnginePermission)) {
|
|
74
|
-
settings.permissions.allow.push(augmentContextEnginePermission);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return settings;
|
|
78
43
|
}
|
|
79
|
-
function mergeClaudeSettingsWithDefaults(settings
|
|
80
|
-
const defaults = buildDefaultClaudeSettings(
|
|
44
|
+
function mergeClaudeSettingsWithDefaults(settings) {
|
|
45
|
+
const defaults = buildDefaultClaudeSettings();
|
|
81
46
|
const env = settings?.env && typeof settings.env === "object" ? settings.env : {};
|
|
82
47
|
const permissions = settings?.permissions && typeof settings.permissions === "object" ? settings.permissions : {};
|
|
83
48
|
return {
|
|
@@ -107,138 +72,11 @@ function applyClaudeInsecureTlsSetting(env = {}, enabled = false) {
|
|
|
107
72
|
return nextEnv;
|
|
108
73
|
}
|
|
109
74
|
|
|
110
|
-
function getPreviousManagedClaudePermissions(previousMetadata = {}) {
|
|
111
|
-
return Array.isArray(previousMetadata.managedClaudePermissions)
|
|
112
|
-
? previousMetadata.managedClaudePermissions.filter((value) => typeof value === "string")
|
|
113
|
-
: [];
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function applyClaudePermissionProfile(settings, {
|
|
117
|
-
profile = "standard",
|
|
118
|
-
previousManagedPermissions = []
|
|
119
|
-
} = {}) {
|
|
120
|
-
if (!claudePermissionProfiles.includes(profile)) {
|
|
121
|
-
throw new Error(`Unknown Claude permission profile: ${profile}`);
|
|
122
|
-
}
|
|
123
|
-
const hasSettings = settings && typeof settings === "object" && !Array.isArray(settings);
|
|
124
|
-
const nextSettings = hasSettings
|
|
125
|
-
? {
|
|
126
|
-
...settings,
|
|
127
|
-
permissions: settings.permissions && typeof settings.permissions === "object"
|
|
128
|
-
? { ...settings.permissions }
|
|
129
|
-
: {}
|
|
130
|
-
}
|
|
131
|
-
: buildDefaultClaudeSettings();
|
|
132
|
-
const allow = Array.isArray(nextSettings.permissions.allow)
|
|
133
|
-
? [...nextSettings.permissions.allow]
|
|
134
|
-
: [];
|
|
135
|
-
const previousManaged = new Set(previousManagedPermissions.filter((value) => typeof value === "string"));
|
|
136
|
-
const retainedManaged = [];
|
|
137
|
-
|
|
138
|
-
for (const permission of previousManaged) {
|
|
139
|
-
if (permission === augmentContextEnginePermission) {
|
|
140
|
-
if (allow.includes(permission)) retainedManaged.push(permission);
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
const index = allow.indexOf(permission);
|
|
144
|
-
if (index !== -1) allow.splice(index, 1);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (profile === "trusted") {
|
|
148
|
-
for (const permission of trustedClaudePermissions) {
|
|
149
|
-
if (allow.includes(permission)) continue;
|
|
150
|
-
allow.push(permission);
|
|
151
|
-
retainedManaged.push(permission);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const previousAllow = Array.isArray(nextSettings.permissions.allow)
|
|
156
|
-
? nextSettings.permissions.allow
|
|
157
|
-
: [];
|
|
158
|
-
nextSettings.permissions.allow = allow;
|
|
159
|
-
return {
|
|
160
|
-
settings: nextSettings,
|
|
161
|
-
changed: !hasSettings || previousAllow.length !== allow.length
|
|
162
|
-
|| previousAllow.some((permission, index) => permission !== allow[index]),
|
|
163
|
-
managedPermissions: [...new Set(retainedManaged)]
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function applyClaudePermissionFeature(settings, {
|
|
168
|
-
augmentContextEngine = false,
|
|
169
|
-
previousManagedPermissions = []
|
|
170
|
-
} = {}) {
|
|
171
|
-
const hasSettings = settings && typeof settings === "object";
|
|
172
|
-
const wasManaged = previousManagedPermissions.includes(augmentContextEnginePermission);
|
|
173
|
-
if (!hasSettings && !augmentContextEngine) {
|
|
174
|
-
return { settings, changed: false, managedPermissions: [] };
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const nextSettings = hasSettings
|
|
178
|
-
? {
|
|
179
|
-
...settings,
|
|
180
|
-
permissions: settings.permissions && typeof settings.permissions === "object"
|
|
181
|
-
? { ...settings.permissions }
|
|
182
|
-
: {}
|
|
183
|
-
}
|
|
184
|
-
: { permissions: {} };
|
|
185
|
-
const permissions = nextSettings.permissions;
|
|
186
|
-
const allow = Array.isArray(permissions.allow)
|
|
187
|
-
? [...permissions.allow]
|
|
188
|
-
: [];
|
|
189
|
-
let changed = !hasSettings;
|
|
190
|
-
let isManaged = wasManaged;
|
|
191
|
-
|
|
192
|
-
if (augmentContextEngine) {
|
|
193
|
-
if (!allow.includes(augmentContextEnginePermission)) {
|
|
194
|
-
allow.push(augmentContextEnginePermission);
|
|
195
|
-
changed = true;
|
|
196
|
-
isManaged = true;
|
|
197
|
-
}
|
|
198
|
-
} else if (wasManaged && allow.includes(augmentContextEnginePermission)) {
|
|
199
|
-
allow.splice(allow.indexOf(augmentContextEnginePermission), 1);
|
|
200
|
-
changed = true;
|
|
201
|
-
isManaged = false;
|
|
202
|
-
} else {
|
|
203
|
-
isManaged = false;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
permissions.allow = allow;
|
|
207
|
-
nextSettings.permissions = permissions;
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
settings: nextSettings,
|
|
211
|
-
changed,
|
|
212
|
-
managedPermissions: [
|
|
213
|
-
...previousManagedPermissions.filter((permission) => permission !== augmentContextEnginePermission && allow.includes(permission)),
|
|
214
|
-
...(isManaged ? [augmentContextEnginePermission] : [])
|
|
215
|
-
]
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async function ensureClaudeSettingsForFeature(paths, augmentContextEngine, previousMetadata) {
|
|
220
|
-
const settingsExists = await pathExists(paths.claudeSettingsPath);
|
|
221
|
-
const settings = settingsExists
|
|
222
|
-
? await readJsonFileSafe(paths.claudeSettingsPath, {}, { sensitive: true })
|
|
223
|
-
: undefined;
|
|
224
|
-
const result = applyClaudePermissionFeature(settings, {
|
|
225
|
-
augmentContextEngine,
|
|
226
|
-
previousManagedPermissions: getPreviousManagedClaudePermissions(previousMetadata)
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
if (result.changed && result.settings) {
|
|
230
|
-
await writeJsonFileWithBackup(paths.claudeSettingsPath, result.settings, { sensitive: true });
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return result.managedPermissions;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
75
|
function getExistingClaudeApiConfig(settings) {
|
|
237
76
|
const env = mergeClaudeSettingsWithDefaults(settings).env;
|
|
238
77
|
return {
|
|
239
78
|
baseUrl: env.ANTHROPIC_BASE_URL || "https://api.anthropic.com",
|
|
240
|
-
|
|
241
|
-
key: env.ANTHROPIC_AUTH_TOKEN || env.ANTHROPIC_API_KEY || "",
|
|
79
|
+
key: env.ANTHROPIC_API_KEY || "",
|
|
242
80
|
model: claudeModelEnvKeys.map((field) => env[field]).find(Boolean) || "",
|
|
243
81
|
insecureTls: env.NODE_TLS_REJECT_UNAUTHORIZED === "0"
|
|
244
82
|
};
|
|
@@ -269,7 +107,6 @@ function ensureApprovedClaudeApiKey(config, apiKey) {
|
|
|
269
107
|
}
|
|
270
108
|
|
|
271
109
|
function buildClaudeApiSettings(settings, {
|
|
272
|
-
authType,
|
|
273
110
|
baseUrl,
|
|
274
111
|
key,
|
|
275
112
|
model,
|
|
@@ -281,13 +118,8 @@ function buildClaudeApiSettings(settings, {
|
|
|
281
118
|
insecureTls
|
|
282
119
|
);
|
|
283
120
|
nextSettings.env.ANTHROPIC_BASE_URL = baseUrl;
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
delete nextSettings.env.ANTHROPIC_API_KEY;
|
|
287
|
-
} else {
|
|
288
|
-
nextSettings.env.ANTHROPIC_API_KEY = key;
|
|
289
|
-
delete nextSettings.env.ANTHROPIC_AUTH_TOKEN;
|
|
290
|
-
}
|
|
121
|
+
nextSettings.env.ANTHROPIC_API_KEY = key;
|
|
122
|
+
delete nextSettings.env.ANTHROPIC_AUTH_TOKEN;
|
|
291
123
|
for (const field of claudeModelEnvKeys) {
|
|
292
124
|
nextSettings.env[field] = model;
|
|
293
125
|
}
|
|
@@ -299,39 +131,30 @@ async function persistClaudeConfiguration(paths, { settings, metaConfig }) {
|
|
|
299
131
|
await writeJsonFileWithBackup(paths.claudeMetaConfigPath, metaConfig, { sensitive: true });
|
|
300
132
|
}
|
|
301
133
|
|
|
302
|
-
async function configureClaudeApi(paths = defaultPaths, promptApi
|
|
134
|
+
async function configureClaudeApi(paths = defaultPaths, promptApi) {
|
|
303
135
|
const {
|
|
304
136
|
assertNotCancelled,
|
|
305
137
|
confirmOrCancel,
|
|
138
|
+
passwordPromptOptions,
|
|
306
139
|
required,
|
|
307
140
|
requiredUnlessExisting,
|
|
308
|
-
resolvePasswordValue
|
|
309
|
-
selectOrCancel
|
|
141
|
+
resolvePasswordValue
|
|
310
142
|
} = promptApi;
|
|
311
143
|
const settings = await readJsonFileSafe(paths.claudeSettingsPath, {}, { sensitive: true });
|
|
312
144
|
const existing = getExistingClaudeApiConfig(settings);
|
|
313
|
-
const authType = await selectOrCancel({
|
|
314
|
-
message: "Claude Code 第三方 API 认证方式",
|
|
315
|
-
options: [
|
|
316
|
-
{ value: "api_key", label: "API Key" },
|
|
317
|
-
{ value: "auth_token", label: "Auth Token" }
|
|
318
|
-
],
|
|
319
|
-
initialValue: existing.authType
|
|
320
|
-
});
|
|
321
145
|
|
|
322
146
|
const baseUrl = await p.text({
|
|
323
147
|
message: "Claude Code Base URL",
|
|
324
|
-
|
|
148
|
+
initialValue: existing.baseUrl,
|
|
325
149
|
validate: required()
|
|
326
150
|
});
|
|
327
151
|
assertNotCancelled(baseUrl);
|
|
328
152
|
|
|
329
|
-
const key = await p.password(
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
});
|
|
153
|
+
const key = await p.password(passwordPromptOptions(
|
|
154
|
+
"Claude Code API Key",
|
|
155
|
+
existing.key,
|
|
156
|
+
requiredUnlessExisting(existing.key, "API Key 不能为空")
|
|
157
|
+
));
|
|
335
158
|
assertNotCancelled(key);
|
|
336
159
|
const finalKey = resolvePasswordValue(key, existing.key);
|
|
337
160
|
|
|
@@ -342,47 +165,33 @@ async function configureClaudeApi(paths = defaultPaths, promptApi, options = {})
|
|
|
342
165
|
|
|
343
166
|
const model = await p.text({
|
|
344
167
|
message: "Claude Code 模型",
|
|
345
|
-
|
|
168
|
+
initialValue: existing.model || undefined,
|
|
346
169
|
validate: required()
|
|
347
170
|
});
|
|
348
171
|
assertNotCancelled(model);
|
|
349
172
|
|
|
350
173
|
const apiSettings = buildClaudeApiSettings(settings, {
|
|
351
|
-
authType,
|
|
352
174
|
baseUrl,
|
|
353
175
|
key: finalKey,
|
|
354
176
|
model,
|
|
355
177
|
insecureTls
|
|
356
178
|
});
|
|
357
|
-
const profileResult = applyClaudePermissionProfile(apiSettings, {
|
|
358
|
-
profile: options.permissionProfile ?? "standard",
|
|
359
|
-
previousManagedPermissions: options.previousManagedPermissions ?? []
|
|
360
|
-
});
|
|
361
179
|
const metaConfig = await readJsonFileSafe(paths.claudeMetaConfigPath, {}, { sensitive: true });
|
|
362
180
|
metaConfig.hasCompletedOnboarding = true;
|
|
363
181
|
ensureApprovedClaudeApiKey(metaConfig, finalKey);
|
|
364
182
|
await persistClaudeConfiguration(paths, {
|
|
365
|
-
settings:
|
|
183
|
+
settings: apiSettings,
|
|
366
184
|
metaConfig
|
|
367
185
|
});
|
|
368
186
|
|
|
369
|
-
p.log.step(`已更新 ${pathToLabel(paths.claudeSettingsPath, paths.homeDir)} (${
|
|
370
|
-
return {
|
|
371
|
-
managedPermissions: profileResult.managedPermissions,
|
|
372
|
-
permissionProfile: options.permissionProfile ?? "standard"
|
|
373
|
-
};
|
|
187
|
+
p.log.step(`已更新 ${pathToLabel(paths.claudeSettingsPath, paths.homeDir)} (${baseUrl}, ${maskSecret(finalKey)})`);
|
|
374
188
|
}
|
|
375
189
|
|
|
376
|
-
|
|
377
190
|
export {
|
|
378
191
|
applyClaudeInsecureTlsSetting,
|
|
379
|
-
applyClaudePermissionFeature,
|
|
380
|
-
applyClaudePermissionProfile,
|
|
381
192
|
buildClaudeApiSettings,
|
|
382
193
|
buildDefaultClaudeSettings,
|
|
383
194
|
configureClaudeApi,
|
|
384
|
-
ensureClaudeSettingsForFeature,
|
|
385
|
-
getPreviousManagedClaudePermissions,
|
|
386
195
|
mergeClaudeSettingsWithDefaults,
|
|
387
196
|
persistClaudeConfiguration
|
|
388
197
|
};
|
package/lib/providers/codex.mjs
CHANGED
|
@@ -304,6 +304,7 @@ async function configureCodexApi(paths = defaultPaths, promptApi, ownership = {}
|
|
|
304
304
|
const {
|
|
305
305
|
assertNotCancelled,
|
|
306
306
|
confirmOrCancel,
|
|
307
|
+
passwordPromptOptions,
|
|
307
308
|
required,
|
|
308
309
|
requiredUnlessExisting,
|
|
309
310
|
resolvePasswordValue
|
|
@@ -313,18 +314,17 @@ async function configureCodexApi(paths = defaultPaths, promptApi, ownership = {}
|
|
|
313
314
|
const providerName = existing.providerName || providerId;
|
|
314
315
|
const baseUrlInput = await p.text({
|
|
315
316
|
message: "Codex Base URL",
|
|
316
|
-
|
|
317
|
+
initialValue: existing.baseUrl,
|
|
317
318
|
validate: required()
|
|
318
319
|
});
|
|
319
320
|
assertNotCancelled(baseUrlInput);
|
|
320
321
|
const baseUrl = normalizeOpenAiBaseUrl(baseUrlInput);
|
|
321
322
|
|
|
322
|
-
const apiKey = await p.password(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
});
|
|
323
|
+
const apiKey = await p.password(passwordPromptOptions(
|
|
324
|
+
"Codex 第三方 API Key",
|
|
325
|
+
existing.apiKey,
|
|
326
|
+
requiredUnlessExisting(existing.apiKey, "API Key 不能为空")
|
|
327
|
+
));
|
|
328
328
|
assertNotCancelled(apiKey);
|
|
329
329
|
const finalApiKey = resolvePasswordValue(apiKey, existing.apiKey);
|
|
330
330
|
|