abelworkflow 1.2.3 → 1.3.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 +26 -25
- package/extensions/gpt-responses-compat.ts +166 -27
- package/lib/cli/main.mjs +18 -86
- package/lib/cli/pi.mjs +43 -0
- package/lib/cli/prompts.mjs +3 -3
- package/lib/installer/assets.mjs +35 -31
- package/lib/installer/install.mjs +29 -9
- package/lib/installer/links.mjs +97 -84
- package/lib/paths.mjs +0 -2
- package/lib/providers/claude.mjs +14 -3
- package/lib/providers/codex.mjs +14 -9
- package/lib/providers/pi.mjs +61 -68
- package/lib/providers/skills.mjs +22 -22
- package/lib/providers/url.mjs +32 -1
- package/lib/templates/codex/agents/default.toml +16 -54
- package/lib/templates/codex/agents/explorer.toml +25 -52
- package/lib/templates/codex/agents/planner.toml +23 -77
- package/lib/templates/codex/agents/reviewer.toml +16 -62
- package/lib/templates/codex/agents/worker.toml +30 -64
- package/lib/templates/codex/config-base.toml +0 -6
- package/lib/templates/{workflow/gitignore.template → gitignore.template} +0 -3
- package/lib/tools/cli-installer.mjs +40 -12
- package/package.json +13 -18
- package/lib/templates/workflow/AGENTS.md +0 -50
- package/lib/templates/workflow/commands/abel-design.md +0 -175
- package/lib/templates/workflow/commands/abel-diagnose.md +0 -63
- package/lib/templates/workflow/commands/abel-implement.md +0 -170
- package/lib/templates/workflow/commands/abel-init.md +0 -25
- package/skills/dev-browser/SKILL.md +0 -281
- package/skills/dev-browser/dist/scripts/start.d.ts +0 -1
- package/skills/dev-browser/dist/scripts/start.js +0 -90
- package/skills/dev-browser/dist/src/client.d.ts +0 -92
- package/skills/dev-browser/dist/src/client.js +0 -310
- package/skills/dev-browser/dist/src/entrypoint.d.ts +0 -29
- package/skills/dev-browser/dist/src/entrypoint.js +0 -113
- package/skills/dev-browser/dist/src/index.d.ts +0 -3
- package/skills/dev-browser/dist/src/index.js +0 -1
- package/skills/dev-browser/dist/src/page-api.d.ts +0 -24
- package/skills/dev-browser/dist/src/page-api.js +0 -103
- package/skills/dev-browser/dist/src/relay.d.ts +0 -26
- package/skills/dev-browser/dist/src/relay.js +0 -567
- package/skills/dev-browser/dist/src/runtime.d.ts +0 -34
- package/skills/dev-browser/dist/src/runtime.js +0 -44
- package/skills/dev-browser/dist/src/snapshot/browser-script.d.ts +0 -22
- package/skills/dev-browser/dist/src/snapshot/browser-script.js +0 -868
- package/skills/dev-browser/dist/src/snapshot/index.d.ts +0 -13
- package/skills/dev-browser/dist/src/snapshot/index.js +0 -13
- package/skills/dev-browser/dist/src/snapshot/inject.d.ts +0 -12
- package/skills/dev-browser/dist/src/snapshot/inject.js +0 -12
- package/skills/dev-browser/dist/src/standalone.d.ts +0 -31
- package/skills/dev-browser/dist/src/standalone.js +0 -173
- package/skills/dev-browser/dist/src/startup.d.ts +0 -46
- package/skills/dev-browser/dist/src/startup.js +0 -77
- package/skills/dev-browser/dist/src/target-registry.d.ts +0 -28
- package/skills/dev-browser/dist/src/target-registry.js +0 -134
- package/skills/dev-browser/dist/src/types.d.ts +0 -26
- package/skills/dev-browser/dist/src/types.js +0 -1
- package/skills/dev-browser/package-lock.json +0 -1545
- package/skills/dev-browser/package.json +0 -35
- package/skills/dev-browser/references/scraping.md +0 -144
- package/skills/git-commit/SKILL.md +0 -124
- package/skills/time/SKILL.md +0 -119
- package/skills/time/scripts/time_cli.py +0 -143
package/lib/installer/assets.mjs
CHANGED
|
@@ -19,12 +19,6 @@ const ignoredSkillPathPatterns = [
|
|
|
19
19
|
/(^|\/)build(\/|$)/u
|
|
20
20
|
];
|
|
21
21
|
|
|
22
|
-
const devBrowserRuntimePathPatterns = [
|
|
23
|
-
/^dev-browser\/SKILL\.md$/u,
|
|
24
|
-
/^dev-browser\/package[^/]*\.json$/u,
|
|
25
|
-
/^dev-browser\/(?:dist|references)(?:\/|$)/u
|
|
26
|
-
];
|
|
27
|
-
|
|
28
22
|
function normalizeRelativePath(path) {
|
|
29
23
|
return path.replaceAll("\\", "/");
|
|
30
24
|
}
|
|
@@ -72,13 +66,26 @@ function mapGitignoreTemplate(relativePath) {
|
|
|
72
66
|
return relativePath.replace(/(^|\/)gitignore\.template$/u, "$1.gitignore");
|
|
73
67
|
}
|
|
74
68
|
|
|
75
|
-
function
|
|
69
|
+
function selectedSkillNames(previousManagedFiles = {}, pathPrefix = null) {
|
|
70
|
+
const names = new Set();
|
|
71
|
+
if (typeof pathPrefix === "string" && pathPrefix.startsWith("skills/")) {
|
|
72
|
+
const selected = pathPrefix.slice("skills/".length).split("/")[0];
|
|
73
|
+
if (selected) names.add(selected);
|
|
74
|
+
}
|
|
75
|
+
for (const relativePath of Object.keys(previousManagedFiles)) {
|
|
76
|
+
if (!relativePath.startsWith("skills/")) continue;
|
|
77
|
+
const skillName = relativePath.slice("skills/".length).split("/")[0];
|
|
78
|
+
if (skillName) names.add(skillName);
|
|
79
|
+
}
|
|
80
|
+
return names;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function shouldCopySkillPath(skillsRoot, sourcePath, selectedSkills) {
|
|
76
84
|
const relativePath = normalizeRelativePath(relative(skillsRoot, sourcePath));
|
|
77
85
|
if (!relativePath) return true;
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
}
|
|
86
|
+
const skillName = relativePath.split("/")[0];
|
|
87
|
+
if (selectedSkills && !selectedSkills.has(skillName)) return false;
|
|
88
|
+
if (relativePath.startsWith("abel-")) return false;
|
|
82
89
|
if (/(^|\/)dist(\/|$)/u.test(relativePath)) return false;
|
|
83
90
|
return !ignoredSkillPathPatterns.some((pattern) => pattern.test(relativePath));
|
|
84
91
|
}
|
|
@@ -115,32 +122,29 @@ async function collectFiles(root, outputPrefix, { filter, mapTargetPath } = {})
|
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
async function addAssetTree(manifest, root, outputPrefix, options = {}) {
|
|
118
|
-
if (!(await pathTargetExists(root)))
|
|
119
|
-
if (options.required) throw new Error(`Missing managed asset root: ${root}`);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
125
|
+
if (!(await pathTargetExists(root))) return;
|
|
122
126
|
for (const [key, value] of await collectFiles(root, outputPrefix, options)) manifest.set(key, value);
|
|
123
127
|
}
|
|
124
128
|
|
|
125
|
-
async function collectManagedAssets(paths) {
|
|
129
|
+
async function collectManagedAssets(paths, { previousManagedFiles = {}, pathPrefix = null } = {}) {
|
|
126
130
|
const manifest = new Map();
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
});
|
|
131
|
+
for (const [sourcePath, targetPath] of [
|
|
132
|
+
[join(paths.packageRoot, "README.md"), "README.md"],
|
|
133
|
+
[join(paths.packageRoot, "lib/templates/gitignore.template"), ".gitignore"]
|
|
134
|
+
]) {
|
|
135
|
+
if (!(await pathTargetExists(sourcePath))) throw new Error(`Missing managed asset: ${sourcePath}`);
|
|
136
|
+
const content = await fs.readFile(sourcePath);
|
|
137
|
+
manifest.set(targetPath, {
|
|
138
|
+
content,
|
|
139
|
+
hash: hashBytes(content),
|
|
140
|
+
mode: (await fs.stat(sourcePath)).mode & 0o777
|
|
141
|
+
});
|
|
142
|
+
}
|
|
140
143
|
|
|
144
|
+
const selectedSkills = selectedSkillNames(previousManagedFiles, pathPrefix);
|
|
141
145
|
const skillsRoot = join(paths.packageRoot, "skills");
|
|
142
146
|
await addAssetTree(manifest, skillsRoot, "skills", {
|
|
143
|
-
filter: shouldCopySkillPath,
|
|
147
|
+
filter: (root, sourcePath) => shouldCopySkillPath(root, sourcePath, selectedSkills),
|
|
144
148
|
mapTargetPath: mapGitignoreTemplate
|
|
145
149
|
});
|
|
146
150
|
await addAssetTree(manifest, join(paths.packageRoot, "extensions"), "extensions");
|
|
@@ -264,7 +268,7 @@ async function syncManagedFiles({
|
|
|
264
268
|
const packageVersion = await readPackageVersion(paths);
|
|
265
269
|
const previousMetadata = await readInstallMetadata(paths);
|
|
266
270
|
const previousManagedFiles = await readManagedFiles(paths, previousMetadata);
|
|
267
|
-
const manifest = await collectManagedAssets(paths);
|
|
271
|
+
const manifest = await collectManagedAssets(paths, { previousManagedFiles, pathPrefix });
|
|
268
272
|
const report = createInstallReport();
|
|
269
273
|
const managedFiles = pathPrefix ? { ...previousManagedFiles } : {};
|
|
270
274
|
|
|
@@ -3,10 +3,9 @@ import { join } from "node:path";
|
|
|
3
3
|
import { createPaths } from "../paths.mjs";
|
|
4
4
|
import { readPackageVersion, syncManagedFiles } from "./assets.mjs";
|
|
5
5
|
import {
|
|
6
|
-
linkClaude,
|
|
7
|
-
linkCodex,
|
|
8
6
|
linkPi,
|
|
9
|
-
linkPiExtensions
|
|
7
|
+
linkPiExtensions,
|
|
8
|
+
linkPiSkill
|
|
10
9
|
} from "./links.mjs";
|
|
11
10
|
import { withDeploymentLock } from "./lock.mjs";
|
|
12
11
|
import {
|
|
@@ -139,9 +138,10 @@ async function installWorkflowLocked(paths, options, guard) {
|
|
|
139
138
|
onResult: (result) => linkResults.push(result)
|
|
140
139
|
};
|
|
141
140
|
try {
|
|
142
|
-
await
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
await linkPi(paths, previousLinkedTargets, {
|
|
142
|
+
...linkOptions,
|
|
143
|
+
managedFiles: assetResult.managedFiles
|
|
144
|
+
});
|
|
145
145
|
} catch (error) {
|
|
146
146
|
await writeInstallState(
|
|
147
147
|
paths,
|
|
@@ -171,6 +171,7 @@ async function installWorkflow(options) {
|
|
|
171
171
|
async function ensureSkillPresentLocked(paths, validatedName, guard) {
|
|
172
172
|
await guard();
|
|
173
173
|
const previousMetadata = await readInstallMetadata(paths);
|
|
174
|
+
const previousLinkedTargets = previousMetadata.linkedTargets ?? {};
|
|
174
175
|
const markIncomplete = onceAsync(() => writeIncompleteInstallState(paths, previousMetadata, guard));
|
|
175
176
|
const beforeMutation = async () => {
|
|
176
177
|
await guard();
|
|
@@ -188,16 +189,35 @@ async function ensureSkillPresentLocked(paths, validatedName, guard) {
|
|
|
188
189
|
await markIncomplete();
|
|
189
190
|
throw error;
|
|
190
191
|
}
|
|
192
|
+
const linkResults = [];
|
|
193
|
+
try {
|
|
194
|
+
await linkPiSkill(paths, validatedName, previousLinkedTargets, {
|
|
195
|
+
force: false,
|
|
196
|
+
beforeMutation,
|
|
197
|
+
onResult: (result) => linkResults.push(result),
|
|
198
|
+
managedFiles: assetResult.managedFiles
|
|
199
|
+
});
|
|
200
|
+
} catch (error) {
|
|
201
|
+
await writeInstallState(
|
|
202
|
+
paths,
|
|
203
|
+
assetResult,
|
|
204
|
+
mergeLinkedTargets(previousLinkedTargets, linkResults),
|
|
205
|
+
false,
|
|
206
|
+
guard
|
|
207
|
+
);
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
const report = mergeInstallReports(assetResult.report, reportFromLinkResults(linkResults));
|
|
191
211
|
await writeInstallState(
|
|
192
212
|
paths,
|
|
193
213
|
assetResult,
|
|
194
|
-
|
|
214
|
+
mergeLinkedTargets(previousLinkedTargets, linkResults),
|
|
195
215
|
previousMetadata.workflowInstalled === true
|
|
196
216
|
&& previousMetadata.packageVersion === assetResult.packageVersion
|
|
197
|
-
&&
|
|
217
|
+
&& report.conflicts.length === 0,
|
|
198
218
|
guard
|
|
199
219
|
);
|
|
200
|
-
return
|
|
220
|
+
return report;
|
|
201
221
|
}
|
|
202
222
|
|
|
203
223
|
async function ensureSkillPresent(inputPaths, skillName, continuation) {
|
package/lib/installer/links.mjs
CHANGED
|
@@ -228,29 +228,6 @@ async function ensureProviderRootDirectory(homeDir, segments, options = {}) {
|
|
|
228
228
|
return directory;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
async function getDirectoryNames(root) {
|
|
232
|
-
if (!(await pathIsDirectory(root))) return [];
|
|
233
|
-
const entries = await fs.readdir(root, { withFileTypes: true });
|
|
234
|
-
const names = await Promise.all(entries.map(async (entry) => {
|
|
235
|
-
if (entry.isDirectory()) return entry.name;
|
|
236
|
-
if (entry.isSymbolicLink() && await pathIsDirectory(join(root, entry.name))) return entry.name;
|
|
237
|
-
return null;
|
|
238
|
-
}));
|
|
239
|
-
return names.filter(Boolean);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async function getCommandNames(commandsDir) {
|
|
243
|
-
if (!(await pathIsDirectory(commandsDir))) return [];
|
|
244
|
-
const entries = await fs.readdir(commandsDir, { withFileTypes: true });
|
|
245
|
-
const names = await Promise.all(entries.map(async (entry) => {
|
|
246
|
-
if (!entry.name.endsWith(".md")) return null;
|
|
247
|
-
if (entry.isFile()) return entry.name;
|
|
248
|
-
if (entry.isSymbolicLink() && await pathIsFile(join(commandsDir, entry.name))) return entry.name;
|
|
249
|
-
return null;
|
|
250
|
-
}));
|
|
251
|
-
return names.filter(Boolean);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
231
|
async function getPiExtensionNames(extensionsDir) {
|
|
255
232
|
if (!(await pathIsDirectory(extensionsDir))) return [];
|
|
256
233
|
const entries = await fs.readdir(extensionsDir, { withFileTypes: true });
|
|
@@ -289,10 +266,48 @@ async function pruneManagedTargets(targetDir, managedSourceRoot, expectedNames,
|
|
|
289
266
|
return results;
|
|
290
267
|
}
|
|
291
268
|
|
|
292
|
-
|
|
269
|
+
const cadenceOwnedSkills = new Set(["grok-search", "context7-auto-research"]);
|
|
270
|
+
|
|
271
|
+
function shouldLinkSkillToPi(skillName) {
|
|
272
|
+
return skillName !== ".system"
|
|
273
|
+
&& !skillName.startsWith("abel-")
|
|
274
|
+
&& !cadenceOwnedSkills.has(skillName);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function managedSkillNames(managedFiles = {}) {
|
|
278
|
+
const names = new Set();
|
|
279
|
+
for (const relativePath of Object.keys(managedFiles)) {
|
|
280
|
+
if (!relativePath.startsWith("skills/")) continue;
|
|
281
|
+
const skillName = relativePath.slice("skills/".length).split("/")[0];
|
|
282
|
+
if (shouldLinkSkillToPi(skillName)) names.add(skillName);
|
|
283
|
+
}
|
|
284
|
+
return names;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function selectedLinkedSkillNames({
|
|
288
|
+
previousLinkedTargets = {},
|
|
289
|
+
skillsRoot,
|
|
290
|
+
managedFiles,
|
|
291
|
+
extraName = null
|
|
292
|
+
} = {}) {
|
|
293
|
+
const names = managedFiles ? managedSkillNames(managedFiles) : new Set();
|
|
294
|
+
if (!managedFiles && skillsRoot) {
|
|
295
|
+
const resolvedSkillsRoot = resolve(skillsRoot);
|
|
296
|
+
for (const previousState of Object.values(previousLinkedTargets)) {
|
|
297
|
+
if (!previousState || previousState.kind !== "dir") continue;
|
|
298
|
+
const sourcePath = resolve(previousState.sourcePath);
|
|
299
|
+
if (dirname(sourcePath) !== resolvedSkillsRoot) continue;
|
|
300
|
+
const skillName = basename(sourcePath);
|
|
301
|
+
if (shouldLinkSkillToPi(skillName)) names.add(skillName);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (extraName && shouldLinkSkillToPi(extraName)) names.add(extraName);
|
|
305
|
+
return [...names];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function linkSkillDirectories(baseDir, paths, previousLinkedTargets, options, skillNames) {
|
|
293
309
|
const results = [];
|
|
294
310
|
const skillsRoot = join(paths.agentsDir, "skills");
|
|
295
|
-
const skillNames = (await getDirectoryNames(skillsRoot)).filter((skillName) => skillName !== ".system");
|
|
296
311
|
results.push(...await pruneManagedTargets(
|
|
297
312
|
join(baseDir, "skills"),
|
|
298
313
|
skillsRoot,
|
|
@@ -312,57 +327,54 @@ async function linkSkillDirectories(baseDir, paths, previousLinkedTargets, optio
|
|
|
312
327
|
return results;
|
|
313
328
|
}
|
|
314
329
|
|
|
315
|
-
async function
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
330
|
+
async function linkPiSkill(paths, skillName, previousLinkedTargets = {}, options = {}) {
|
|
331
|
+
if (!shouldLinkSkillToPi(skillName)) return [];
|
|
332
|
+
const piAgentDir = await ensureProviderRootDirectory(paths.homeDir, [".pi", "agent"], options);
|
|
333
|
+
await ensureManagedContainerDirectories([join(piAgentDir, "skills")], options);
|
|
334
|
+
const skillsRoot = join(paths.agentsDir, "skills");
|
|
335
|
+
return linkSkillDirectories(
|
|
336
|
+
piAgentDir,
|
|
337
|
+
paths,
|
|
338
|
+
previousLinkedTargets,
|
|
339
|
+
options,
|
|
340
|
+
selectedLinkedSkillNames({
|
|
324
341
|
previousLinkedTargets,
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
342
|
+
skillsRoot,
|
|
343
|
+
managedFiles: options.managedFiles,
|
|
344
|
+
extraName: skillName
|
|
345
|
+
})
|
|
346
|
+
);
|
|
329
347
|
}
|
|
330
348
|
|
|
331
|
-
async function
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
join(paths.agentsDir, "AGENTS.md"),
|
|
341
|
-
"file",
|
|
342
|
-
previousLinkedTargets,
|
|
343
|
-
options
|
|
344
|
-
));
|
|
345
|
-
results.push(...await linkCommands(join(claudeDir, "commands"), paths, previousLinkedTargets, options));
|
|
346
|
-
results.push(...await linkSkillDirectories(claudeDir, paths, previousLinkedTargets, options));
|
|
347
|
-
return results;
|
|
349
|
+
async function pruneProviderInstructions(baseDir, commandsName, paths, previousLinkedTargets, options) {
|
|
350
|
+
const cleanupOptions = {
|
|
351
|
+
...options,
|
|
352
|
+
validateTargetDir: (directory) => ensureManagedContainerDirectories([directory], options)
|
|
353
|
+
};
|
|
354
|
+
return [
|
|
355
|
+
...await pruneManagedTargets(baseDir, paths.agentsDir, [], previousLinkedTargets, cleanupOptions),
|
|
356
|
+
...await pruneManagedTargets(join(baseDir, commandsName), join(paths.agentsDir, "commands"), [], previousLinkedTargets, cleanupOptions)
|
|
357
|
+
];
|
|
348
358
|
}
|
|
349
359
|
|
|
350
|
-
async function
|
|
351
|
-
const codexDir = await ensureProviderRootDirectory(paths.homeDir, [".codex"], options);
|
|
352
|
-
await ensureManagedContainerDirectories([
|
|
353
|
-
join(codexDir, "skills"),
|
|
354
|
-
join(codexDir, "prompts")
|
|
355
|
-
], options);
|
|
360
|
+
async function pruneRetiredProviderLinks(paths, previousLinkedTargets = {}, options = {}) {
|
|
356
361
|
const results = [];
|
|
357
|
-
|
|
358
|
-
join(
|
|
359
|
-
join(paths.
|
|
360
|
-
"
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
362
|
+
for (const targetDir of [
|
|
363
|
+
join(paths.homeDir, ".claude"),
|
|
364
|
+
join(paths.homeDir, ".claude", "commands"),
|
|
365
|
+
join(paths.homeDir, ".claude", "skills"),
|
|
366
|
+
join(paths.homeDir, ".codex"),
|
|
367
|
+
join(paths.homeDir, ".codex", "prompts"),
|
|
368
|
+
join(paths.homeDir, ".codex", "skills")
|
|
369
|
+
]) {
|
|
370
|
+
results.push(...await pruneManagedTargets(
|
|
371
|
+
targetDir,
|
|
372
|
+
paths.agentsDir,
|
|
373
|
+
[],
|
|
374
|
+
previousLinkedTargets,
|
|
375
|
+
options
|
|
376
|
+
));
|
|
377
|
+
}
|
|
366
378
|
return results;
|
|
367
379
|
}
|
|
368
380
|
|
|
@@ -404,19 +416,21 @@ async function linkPi(paths, previousLinkedTargets = {}, options = {}) {
|
|
|
404
416
|
const piAgentDir = await ensureProviderRootDirectory(paths.homeDir, [".pi", "agent"], options);
|
|
405
417
|
await ensureManagedContainerDirectories([
|
|
406
418
|
join(piAgentDir, "extensions"),
|
|
407
|
-
join(piAgentDir, "skills")
|
|
408
|
-
join(piAgentDir, "prompts")
|
|
419
|
+
join(piAgentDir, "skills")
|
|
409
420
|
], options);
|
|
410
|
-
const results =
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
421
|
+
const results = await pruneRetiredProviderLinks(paths, previousLinkedTargets, options);
|
|
422
|
+
results.push(...await pruneProviderInstructions(piAgentDir, "prompts", paths, previousLinkedTargets, options));
|
|
423
|
+
results.push(...await linkSkillDirectories(
|
|
424
|
+
piAgentDir,
|
|
425
|
+
paths,
|
|
415
426
|
previousLinkedTargets,
|
|
416
|
-
options
|
|
427
|
+
options,
|
|
428
|
+
selectedLinkedSkillNames({
|
|
429
|
+
previousLinkedTargets,
|
|
430
|
+
skillsRoot: join(paths.agentsDir, "skills"),
|
|
431
|
+
managedFiles: options.managedFiles
|
|
432
|
+
})
|
|
417
433
|
));
|
|
418
|
-
results.push(...await linkSkillDirectories(piAgentDir, paths, previousLinkedTargets, options));
|
|
419
|
-
results.push(...await linkCommands(join(piAgentDir, "prompts"), paths, previousLinkedTargets, options));
|
|
420
434
|
results.push(...await linkPiExtensionsInDirectory(
|
|
421
435
|
join(piAgentDir, "extensions"),
|
|
422
436
|
join(paths.agentsDir, "extensions"),
|
|
@@ -429,11 +443,10 @@ async function linkPi(paths, previousLinkedTargets = {}, options = {}) {
|
|
|
429
443
|
export {
|
|
430
444
|
ensureManagedLink,
|
|
431
445
|
ensureProviderRootDirectory,
|
|
432
|
-
getCommandNames,
|
|
433
446
|
isWithinManagedRoot,
|
|
434
|
-
linkClaude,
|
|
435
|
-
linkCodex,
|
|
436
447
|
linkPi,
|
|
437
448
|
linkPiExtensions,
|
|
438
|
-
|
|
449
|
+
linkPiSkill,
|
|
450
|
+
pruneManagedTargets,
|
|
451
|
+
shouldLinkSkillToPi
|
|
439
452
|
};
|
package/lib/paths.mjs
CHANGED
|
@@ -16,13 +16,11 @@ function createPaths({
|
|
|
16
16
|
assertSeparateSourceAndDeployment(absolutePackageRoot, absoluteAgentsDir);
|
|
17
17
|
|
|
18
18
|
const codexTemplateRoot = join(absolutePackageRoot, "lib", "templates", "codex");
|
|
19
|
-
const workflowTemplateRoot = join(absolutePackageRoot, "lib", "templates", "workflow");
|
|
20
19
|
const piAgentDir = join(absoluteHomeDir, ".pi", "agent");
|
|
21
20
|
return {
|
|
22
21
|
homeDir: absoluteHomeDir,
|
|
23
22
|
packageRoot: absolutePackageRoot,
|
|
24
23
|
agentsDir: absoluteAgentsDir,
|
|
25
|
-
workflowTemplateRoot,
|
|
26
24
|
installMetadataName: ".abelworkflow-install.json",
|
|
27
25
|
claudeSettingsPath: join(absoluteHomeDir, ".claude", "settings.json"),
|
|
28
26
|
codexConfigPath: join(absoluteHomeDir, ".codex", "config.toml"),
|
package/lib/providers/claude.mjs
CHANGED
|
@@ -50,8 +50,15 @@ const defaultClaudeSettings = {
|
|
|
50
50
|
language: "Chinese"
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
function assertClaudeApiKey(value, label) {
|
|
54
|
+
if (value !== undefined && typeof value !== "string") {
|
|
55
|
+
throw new TypeError(`${label} must be a string or undefined`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
53
59
|
function getExistingClaudeApiConfig(settings) {
|
|
54
60
|
const env = settings.env === undefined ? {} : assertPlainObject(settings.env, "Claude settings env");
|
|
61
|
+
assertClaudeApiKey(env.ANTHROPIC_API_KEY, "Claude settings env ANTHROPIC_API_KEY");
|
|
55
62
|
return {
|
|
56
63
|
baseUrl: env.ANTHROPIC_BASE_URL || "https://api.anthropic.com",
|
|
57
64
|
key: env.ANTHROPIC_API_KEY || "",
|
|
@@ -66,6 +73,8 @@ function buildClaudeApiSettings(settings, {
|
|
|
66
73
|
}) {
|
|
67
74
|
assertPlainObject(settings, "Claude settings");
|
|
68
75
|
const env = settings.env === undefined ? {} : assertPlainObject(settings.env, "Claude settings env");
|
|
76
|
+
assertClaudeApiKey(env.ANTHROPIC_API_KEY, "Claude settings env ANTHROPIC_API_KEY");
|
|
77
|
+
assertClaudeApiKey(key, "Claude API key");
|
|
69
78
|
const permissions = settings.permissions === undefined
|
|
70
79
|
? {}
|
|
71
80
|
: assertPlainObject(settings.permissions, "Claude settings permissions");
|
|
@@ -82,8 +91,7 @@ function buildClaudeApiSettings(settings, {
|
|
|
82
91
|
env: {
|
|
83
92
|
...defaultClaudeSettings.env,
|
|
84
93
|
...env,
|
|
85
|
-
ANTHROPIC_BASE_URL: normalizeHttpBaseUrl(baseUrl)
|
|
86
|
-
ANTHROPIC_API_KEY: key
|
|
94
|
+
ANTHROPIC_BASE_URL: normalizeHttpBaseUrl(baseUrl)
|
|
87
95
|
},
|
|
88
96
|
permissions: {
|
|
89
97
|
...defaultClaudeSettings.permissions,
|
|
@@ -92,6 +100,8 @@ function buildClaudeApiSettings(settings, {
|
|
|
92
100
|
deny: Array.isArray(permissions.deny) ? permissions.deny : [...defaultClaudeSettings.permissions.deny]
|
|
93
101
|
}
|
|
94
102
|
};
|
|
103
|
+
if (key === undefined) delete nextSettings.env.ANTHROPIC_API_KEY;
|
|
104
|
+
else nextSettings.env.ANTHROPIC_API_KEY = key;
|
|
95
105
|
delete nextSettings.includeCoAuthoredBy;
|
|
96
106
|
delete nextSettings.env.ANTHROPIC_AUTH_TOKEN;
|
|
97
107
|
delete nextSettings.env.DISABLE_TELEMETRY;
|
|
@@ -144,7 +154,8 @@ async function configureClaudeApi(paths, promptApi, runtime = {}) {
|
|
|
144
154
|
|
|
145
155
|
const finalKey = await passwordOrExisting({
|
|
146
156
|
message: "Claude Code API Key",
|
|
147
|
-
existingValue: existing.key
|
|
157
|
+
existingValue: existing.key,
|
|
158
|
+
requiredMessage: existing.key ? null : "API Key 不能为空"
|
|
148
159
|
});
|
|
149
160
|
|
|
150
161
|
const model = await text({
|
package/lib/providers/codex.mjs
CHANGED
|
@@ -62,7 +62,10 @@ function mergeCodexTemplateDefaults(content, templateContent) {
|
|
|
62
62
|
? current.developer_instructions
|
|
63
63
|
: "";
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
const instructionHash = hashBytes(currentInstructions);
|
|
66
|
+
const usesLegacyDefaults = publishedCodexDeveloperInstructionHashes.has(instructionHash);
|
|
67
|
+
if (usesLegacyDefaults
|
|
68
|
+
|| instructionHash === "c84017d17fa425175f6dd7df9766b5de74e289420f63fea87054e2f41822a8bc") {
|
|
66
69
|
const legacyDefaults = {
|
|
67
70
|
approvals_reviewer: "guardian_subagent",
|
|
68
71
|
approval_policy: "on-request",
|
|
@@ -71,7 +74,7 @@ function mergeCodexTemplateDefaults(content, templateContent) {
|
|
|
71
74
|
};
|
|
72
75
|
const replacementFields = new Set(["developer_instructions"]);
|
|
73
76
|
for (const [field, value] of Object.entries(legacyDefaults)) {
|
|
74
|
-
if (current[field] === value) replacementFields.add(field);
|
|
77
|
+
if (usesLegacyDefaults && current[field] === value) replacementFields.add(field);
|
|
75
78
|
}
|
|
76
79
|
for (const field of replacementFields) {
|
|
77
80
|
nextContent = removeTopLevelTomlField(nextContent, field);
|
|
@@ -375,15 +378,17 @@ function buildCodexConfigContent(currentContent, {
|
|
|
375
378
|
|
|
376
379
|
function mergeCodexAuthData(auth, apiKey) {
|
|
377
380
|
assertPlainObject(auth, "Codex auth");
|
|
378
|
-
|
|
379
|
-
assertCodexAuthKeyAvailable(nextAuth, CODEX_ENV_KEY);
|
|
381
|
+
assertCodexAuthKeyAvailable(auth, CODEX_ENV_KEY);
|
|
380
382
|
if (apiKey) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
if (nextAuth.auth_mode === "apikey") delete nextAuth.auth_mode;
|
|
383
|
+
return {
|
|
384
|
+
auth_mode: "apikey",
|
|
385
|
+
[CODEX_ENV_KEY]: apiKey
|
|
386
|
+
};
|
|
386
387
|
}
|
|
388
|
+
|
|
389
|
+
const nextAuth = { ...auth };
|
|
390
|
+
delete nextAuth[CODEX_ENV_KEY];
|
|
391
|
+
if (nextAuth.auth_mode === "apikey") delete nextAuth.auth_mode;
|
|
387
392
|
return nextAuth;
|
|
388
393
|
}
|
|
389
394
|
|