abelworkflow 0.9.2 → 1.0.0-rc.1
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 +55 -182
- package/bin/abelworkflow.mjs +5 -3
- package/lib/cli/args.mjs +76 -0
- package/lib/cli/main.mjs +387 -0
- package/lib/cli/prompts.mjs +119 -0
- package/lib/config/dotenv.mjs +102 -0
- package/lib/config/jsonc.mjs +80 -0
- package/lib/config/store.mjs +310 -0
- package/lib/config/toml.mjs +638 -0
- package/lib/installer/assets.mjs +326 -0
- package/lib/installer/install.mjs +167 -0
- package/lib/installer/links.mjs +427 -0
- package/lib/installer/render.mjs +46 -0
- package/lib/installer/state.mjs +182 -0
- package/lib/paths.mjs +99 -0
- package/lib/providers/claude.mjs +388 -0
- package/lib/providers/codex.mjs +433 -0
- package/lib/providers/pi.mjs +362 -0
- package/lib/providers/skills.mjs +164 -0
- package/lib/templates/codex/agents/default.toml +7 -0
- package/lib/templates/codex/agents/explorer.toml +7 -0
- package/lib/templates/codex/agents/planner.toml +7 -0
- package/lib/templates/codex/agents/reviewer.toml +7 -0
- package/lib/templates/codex/agents/worker.toml +7 -0
- package/lib/templates/codex/config-base.toml +11 -3
- package/{AGENTS.md → lib/templates/workflow/AGENTS.md} +8 -3
- package/{commands → lib/templates/workflow/commands}/abel-diagnose.md +5 -5
- package/{commands → lib/templates/workflow/commands}/abel-implement.md +3 -8
- package/{commands → lib/templates/workflow/commands}/abel-init.md +1 -1
- package/{commands → lib/templates/workflow/commands}/abel-plan.md +1 -7
- package/{commands → lib/templates/workflow/commands}/abel-research.md +1 -1
- package/{.gitignore → lib/templates/workflow/gitignore.template} +0 -2
- package/lib/tools/cli-installer.mjs +277 -0
- package/package.json +43 -10
- package/skills/context7-auto-research/SKILL.md +5 -5
- package/skills/context7-auto-research/{context7-api.js → context7-api.cjs} +5 -8
- package/skills/dev-browser/SKILL.md +53 -33
- package/skills/dev-browser/dist/scripts/start.d.ts +2 -0
- package/skills/dev-browser/dist/scripts/start.d.ts.map +1 -0
- package/skills/dev-browser/dist/scripts/start.js +118 -0
- package/skills/dev-browser/dist/scripts/start.js.map +1 -0
- package/skills/dev-browser/dist/src/client.d.ts +93 -0
- package/skills/dev-browser/dist/src/client.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/client.js +310 -0
- package/skills/dev-browser/dist/src/client.js.map +1 -0
- package/skills/dev-browser/dist/src/entrypoint.d.ts +29 -0
- package/skills/dev-browser/dist/src/entrypoint.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/entrypoint.js +106 -0
- package/skills/dev-browser/dist/src/entrypoint.js.map +1 -0
- package/skills/dev-browser/dist/src/index.d.ts +4 -0
- package/skills/dev-browser/dist/src/index.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/index.js +2 -0
- package/skills/dev-browser/dist/src/index.js.map +1 -0
- package/skills/dev-browser/dist/src/page-api.d.ts +25 -0
- package/skills/dev-browser/dist/src/page-api.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/page-api.js +104 -0
- package/skills/dev-browser/dist/src/page-api.js.map +1 -0
- package/skills/dev-browser/dist/src/relay.d.ts +27 -0
- package/skills/dev-browser/dist/src/relay.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/relay.js +521 -0
- package/skills/dev-browser/dist/src/relay.js.map +1 -0
- package/skills/dev-browser/dist/src/runtime.d.ts +45 -0
- package/skills/dev-browser/dist/src/runtime.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/runtime.js +54 -0
- package/skills/dev-browser/dist/src/runtime.js.map +1 -0
- package/skills/dev-browser/dist/src/snapshot/browser-script.d.ts +23 -0
- package/skills/dev-browser/dist/src/snapshot/browser-script.d.ts.map +1 -0
- package/skills/dev-browser/{src/snapshot/browser-script.ts → dist/src/snapshot/browser-script.js} +21 -30
- package/skills/dev-browser/dist/src/snapshot/browser-script.js.map +1 -0
- package/skills/dev-browser/dist/src/snapshot/index.d.ts +14 -0
- package/skills/dev-browser/dist/src/snapshot/index.d.ts.map +1 -0
- package/skills/dev-browser/{src/snapshot/index.ts → dist/src/snapshot/index.js} +2 -2
- package/skills/dev-browser/dist/src/snapshot/index.js.map +1 -0
- package/skills/dev-browser/dist/src/snapshot/inject.d.ts +13 -0
- package/skills/dev-browser/dist/src/snapshot/inject.d.ts.map +1 -0
- package/skills/dev-browser/{src/snapshot/inject.ts → dist/src/snapshot/inject.js} +2 -2
- package/skills/dev-browser/dist/src/snapshot/inject.js.map +1 -0
- package/skills/dev-browser/dist/src/standalone.d.ts +32 -0
- package/skills/dev-browser/dist/src/standalone.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/standalone.js +174 -0
- package/skills/dev-browser/dist/src/standalone.js.map +1 -0
- package/skills/dev-browser/dist/src/startup.d.ts +55 -0
- package/skills/dev-browser/dist/src/startup.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/startup.js +81 -0
- package/skills/dev-browser/dist/src/startup.js.map +1 -0
- package/skills/dev-browser/dist/src/target-registry.d.ts +29 -0
- package/skills/dev-browser/dist/src/target-registry.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/target-registry.js +135 -0
- package/skills/dev-browser/dist/src/target-registry.js.map +1 -0
- package/skills/dev-browser/dist/src/types.d.ts +27 -0
- package/skills/dev-browser/dist/src/types.d.ts.map +1 -0
- package/skills/dev-browser/dist/src/types.js +2 -0
- package/skills/dev-browser/dist/src/types.js.map +1 -0
- package/skills/dev-browser/package-lock.json +67 -1510
- package/skills/dev-browser/package.json +18 -14
- package/skills/dev-browser/references/scraping.md +94 -105
- package/skills/grok-search/defaults.json +3 -0
- package/skills/grok-search/gitignore.template +4 -0
- package/skills/grok-search/scripts/_dotenv.py +5 -1
- package/skills/grok-search/scripts/groksearch_cli.py +15 -33
- package/skills/prompt-enhancer/TEMPLATE.md +0 -4
- package/skills/prompt-enhancer/requirements.txt +0 -1
- package/skills/prompt-enhancer/scripts/_dotenv.py +5 -1
- package/skills/prompt-enhancer/scripts/enhance.py +4 -51
- package/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py +1 -16
- package/.skill-lock.json +0 -29
- package/lib/cli/logic.mjs +0 -213
- package/lib/cli.mjs +0 -3016
- package/skills/confidence-check/SKILL.md +0 -34
- package/skills/confidence-check/confidence.ts +0 -276
- package/skills/dev-browser/bun.lock +0 -460
- package/skills/dev-browser/scripts/start.ts +0 -280
- package/skills/dev-browser/src/client.ts +0 -474
- package/skills/dev-browser/src/entrypoint.ts +0 -157
- package/skills/dev-browser/src/index.ts +0 -289
- package/skills/dev-browser/src/relay.ts +0 -731
- package/skills/dev-browser/src/runtime.test.ts +0 -60
- package/skills/dev-browser/src/runtime.ts +0 -171
- package/skills/dev-browser/src/startup.test.ts +0 -95
- package/skills/dev-browser/src/startup.ts +0 -153
- package/skills/dev-browser/src/types.ts +0 -35
- package/skills/dev-browser/tsconfig.json +0 -36
- package/skills/dev-browser/vitest.config.ts +0 -12
- package/skills/sequential-think/SKILL.md +0 -198
- package/skills/sequential-think/scripts/.env.example +0 -5
- package/skills/sequential-think/scripts/sequential_think_cli.py +0 -253
|
@@ -12,7 +12,7 @@ argument-hint: <problem-description>
|
|
|
12
12
|
**Guardrails**
|
|
13
13
|
- Root cause first; never fix symptoms only
|
|
14
14
|
- Verify root cause hypothesis with evidence before fix
|
|
15
|
-
-
|
|
15
|
+
- Only fixes with evidence-verified root cause may be applied
|
|
16
16
|
- Every fix must include a regression test
|
|
17
17
|
- Keep changes minimal and scoped
|
|
18
18
|
- If verification fails, rollback and iterate
|
|
@@ -32,9 +32,9 @@ argument-hint: <problem-description>
|
|
|
32
32
|
**Steps**
|
|
33
33
|
1. Parse input, infer scope, and split into issue list (single or multiple).
|
|
34
34
|
2. For each issue in parallel: collect logs/traces and locate code via the configured codebase retrieval policy.
|
|
35
|
-
3. For each issue in parallel: perform root cause analysis;
|
|
35
|
+
3. For each issue in parallel: perform root cause analysis; for multi-component chains, decompose the failure chain step by step with evidence.
|
|
36
36
|
4. Build dependency/conflict graph across issues and compute safe fix order.
|
|
37
|
-
5.
|
|
37
|
+
5. Verify each issue's root cause against collected evidence; only issues with a verified root cause can move to fix generation.
|
|
38
38
|
6. Spawn one subagent per READY issue to generate `unified diff patch` and regression test with minimal scoped context.
|
|
39
39
|
7. Main agent reviews/merges subagent outputs by dependency order and outputs one batch report with all issue statuses and patches.
|
|
40
40
|
8. Apply merged patches strictly sequentially by dependency order.
|
|
@@ -42,13 +42,13 @@ argument-hint: <problem-description>
|
|
|
42
42
|
|
|
43
43
|
**Batch Output**
|
|
44
44
|
```text
|
|
45
|
-
## /
|
|
45
|
+
## /abel-diagnose Batch Report
|
|
46
46
|
|
|
47
47
|
### Batch Summary
|
|
48
48
|
Total: {n} | ReadyToFix: {n_ready} | Blocked: {n_blocked}
|
|
49
49
|
|
|
50
50
|
### Issue Results
|
|
51
|
-
- [{id}] Classification: {category}/{severity} | Root Cause: {summary} |
|
|
51
|
+
- [{id}] Classification: {category}/{severity} | Root Cause: {summary} | Verified: {yes|no} | Subagent: {agent_id|none} | Status: {READY|BLOCKED}
|
|
52
52
|
|
|
53
53
|
### Patch Queue (dependency order)
|
|
54
54
|
1. [{id}] [subagent:{agent_id}] {file_list}
|
|
@@ -44,9 +44,6 @@ argument-hint: [change_name]
|
|
|
44
44
|
|
|
45
45
|
```
|
|
46
46
|
┌─────────────────────────────────────────────────────────┐
|
|
47
|
-
│ Step 0: Pre-Check │
|
|
48
|
-
│ └─ /confidence-check → require ≥90% to proceed │
|
|
49
|
-
├─────────────────────────────────────────────────────────┤
|
|
50
47
|
│ Step 1: 🔴 Red Phase - Generate Failing Test │
|
|
51
48
|
│ ├─ Analyze task → determine test type │
|
|
52
49
|
│ │ ├─ Backend → pytest/jest │
|
|
@@ -101,17 +98,15 @@ argument-hint: [change_name]
|
|
|
101
98
|
13. Run all tests → MUST ALL PASS.
|
|
102
99
|
14. If any test fails → analyze root cause, fix or rollback.
|
|
103
100
|
15. Perform final side-effect review.
|
|
104
|
-
16.
|
|
101
|
+
16. Report that the change is ready for archive; do not archive until the user explicitly authorizes `/opsx:archive`.
|
|
105
102
|
|
|
106
103
|
**TDD Output Format**
|
|
107
104
|
|
|
108
105
|
```
|
|
109
|
-
## /
|
|
106
|
+
## /abel-implement (TDD Mode)
|
|
110
107
|
|
|
111
108
|
### Task 1/N: {task_description}
|
|
112
109
|
|
|
113
|
-
📋 Confidence Check: {score}% {status}
|
|
114
|
-
|
|
115
110
|
🔴 Red Phase
|
|
116
111
|
├─ Generated: tests/{test_file}
|
|
117
112
|
├─ Run: {test_command}
|
|
@@ -150,7 +145,7 @@ Frontend Review
|
|
|
150
145
|
✓ Reviews complete
|
|
151
146
|
├─ Applied: {refactoring_summary}
|
|
152
147
|
├─ Tests: {count} passed ✓
|
|
153
|
-
└─ Ready for archive
|
|
148
|
+
└─ Ready for user-authorized archive
|
|
154
149
|
|
|
155
150
|
✓ Implementation complete
|
|
156
151
|
```
|
|
@@ -18,7 +18,7 @@ tags: [openspec, init, setup]
|
|
|
18
18
|
4. Run `openspec init` (or `openspec update` for existing projects).
|
|
19
19
|
5. {{AUGMENT_CONTEXT_ENGINE_VALIDATION}}
|
|
20
20
|
6. Verify required skills:
|
|
21
|
-
- Skills: `/dev-browser` `/
|
|
21
|
+
- Skills: `/dev-browser` `/context7-auto-research` `/grok-search`
|
|
22
22
|
7. Output summary with ✓/✗:
|
|
23
23
|
- OpenSpec installation
|
|
24
24
|
- Project initialization
|
|
@@ -25,14 +25,8 @@ argument-hint: [change_name]
|
|
|
25
25
|
- Check `openspec status --change <change_name>` for artifact completion
|
|
26
26
|
- Use `openspec instructions specs --change <change_name>` for specs guidance
|
|
27
27
|
|
|
28
|
-
3. **Implementation Analysis**:
|
|
28
|
+
3. **Implementation Analysis**: Perform systematic analysis to derive a plan. If the proposal has 3+ interconnected requirements, first break it down into components, identify dependencies, evaluate architectural trade-offs, and surface potential conflicts. Then invoke `/context7-auto-research` to validate framework/library choices:
|
|
29
29
|
```
|
|
30
|
-
# First, invoke /sequential-think skill for systematic analysis if proposal has 3+ interconnected requirements
|
|
31
|
-
|
|
32
|
-
/sequential-think: "Analyze change <change_name> systematically: Break down into components, identify dependencies, evaluate architectural trade-offs, and surface potential conflicts."
|
|
33
|
-
|
|
34
|
-
# Then invoke /context7-auto-research skill to validate framework/library choices
|
|
35
|
-
|
|
36
30
|
/context7-auto-research: "For each technology mentioned in change <change_name>, retrieve official documentation patterns and best practices."
|
|
37
31
|
```
|
|
38
32
|
Produce a consolidated, constraint-complete plan and list any missing constraints as questions to the user.
|
|
@@ -77,7 +77,7 @@ All explore subagents MUST return valid JSON using this schema:
|
|
|
77
77
|
- Clear scope
|
|
78
78
|
- self-contained with independent output
|
|
79
79
|
- Required output template (from Phase 4)
|
|
80
|
-
- If boundary involves 3+ interconnected components,
|
|
80
|
+
- If boundary involves 3+ interconnected components, require explicit step-by-step dependency analysis
|
|
81
81
|
- Clear success criteria: complete analysis of assigned boundary
|
|
82
82
|
|
|
83
83
|
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import * as p from "@clack/prompts";
|
|
4
|
+
import c from "picocolors";
|
|
5
|
+
import { defaultPaths, getPlatform, isWindows } from "../paths.mjs";
|
|
6
|
+
|
|
7
|
+
const { homeDir: home } = defaultPaths;
|
|
8
|
+
|
|
9
|
+
function getRunCommandSpawnOptions(platform = getPlatform()) {
|
|
10
|
+
return { stdio: "inherit", shell: platform === "win32" };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getCommandPath(command) {
|
|
14
|
+
const checker = isWindows() ? "where" : "which";
|
|
15
|
+
const result = spawnSync(checker, [command], { encoding: "utf8" });
|
|
16
|
+
if (result.status !== 0) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
return result.stdout
|
|
20
|
+
.split(/\r?\n/u)
|
|
21
|
+
.map((line) => line.trim())
|
|
22
|
+
.find(Boolean);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function commandExists(command) {
|
|
26
|
+
return Boolean(getCommandPath(command));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function readCommandOutput(command, args) {
|
|
30
|
+
const result = spawnSync(command, args, {
|
|
31
|
+
encoding: "utf8",
|
|
32
|
+
shell: isWindows(),
|
|
33
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
34
|
+
});
|
|
35
|
+
if (result.status !== 0) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
const outputValue = result.stdout.trim();
|
|
39
|
+
return outputValue || undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function runCommand(command, args) {
|
|
43
|
+
await new Promise((resolvePromise, rejectPromise) => {
|
|
44
|
+
const child = spawn(command, args, getRunCommandSpawnOptions(getPlatform()));
|
|
45
|
+
child.on("error", rejectPromise);
|
|
46
|
+
child.on("close", (code) => {
|
|
47
|
+
if (code === 0) {
|
|
48
|
+
resolvePromise();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
rejectPromise(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function normalizeInstallPath(value) {
|
|
57
|
+
if (!value) {
|
|
58
|
+
return "";
|
|
59
|
+
}
|
|
60
|
+
return value.replace(/\\/gu, "/").replace(/\/+$/u, "").toLowerCase();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function installPathIsWithin(path, parentPath) {
|
|
64
|
+
const normalizedPath = normalizeInstallPath(path);
|
|
65
|
+
const normalizedParent = normalizeInstallPath(parentPath);
|
|
66
|
+
return Boolean(normalizedPath && normalizedParent)
|
|
67
|
+
&& (normalizedPath === normalizedParent || normalizedPath.startsWith(`${normalizedParent}/`));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getNpmGlobalBinDirs(npmGlobalPrefix, platform = getPlatform()) {
|
|
71
|
+
if (!npmGlobalPrefix) {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
return platform === "win32" ? [npmGlobalPrefix] : [join(npmGlobalPrefix, "bin")];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function inferPackageManagerFromCommandPath(commandPath, {
|
|
78
|
+
bunGlobalBinDir,
|
|
79
|
+
npmGlobalPrefix,
|
|
80
|
+
platform = getPlatform()
|
|
81
|
+
} = {}) {
|
|
82
|
+
if (installPathIsWithin(commandPath, bunGlobalBinDir)) {
|
|
83
|
+
return "bun";
|
|
84
|
+
}
|
|
85
|
+
if (getNpmGlobalBinDirs(npmGlobalPrefix, platform)
|
|
86
|
+
.some((binDir) => installPathIsWithin(commandPath, binDir))) {
|
|
87
|
+
return "npm";
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function chooseCliInstallPackageManager({
|
|
93
|
+
commandPath,
|
|
94
|
+
availablePackageManagers = [],
|
|
95
|
+
bunGlobalBinDir,
|
|
96
|
+
npmGlobalPrefix,
|
|
97
|
+
platform = getPlatform(),
|
|
98
|
+
nodeAvailable = true,
|
|
99
|
+
supportedPackageManagers = ["bun", "npm"]
|
|
100
|
+
} = {}) {
|
|
101
|
+
const supported = new Set(supportedPackageManagers);
|
|
102
|
+
const available = new Set(availablePackageManagers.filter((packageManager) => {
|
|
103
|
+
if (!supported.has(packageManager)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return packageManager !== "bun" || nodeAvailable;
|
|
107
|
+
}));
|
|
108
|
+
const bunBlockedByMissingNode = !nodeAvailable
|
|
109
|
+
&& supported.has("bun")
|
|
110
|
+
&& availablePackageManagers.includes("bun");
|
|
111
|
+
const existingPackageManager = inferPackageManagerFromCommandPath(commandPath, {
|
|
112
|
+
bunGlobalBinDir,
|
|
113
|
+
npmGlobalPrefix,
|
|
114
|
+
platform
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (existingPackageManager && available.has(existingPackageManager)) {
|
|
118
|
+
return { packageManager: existingPackageManager, source: "existing" };
|
|
119
|
+
}
|
|
120
|
+
for (const packageManager of ["bun", "npm"]) {
|
|
121
|
+
if (available.has(packageManager)) {
|
|
122
|
+
return { packageManager, source: "available" };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
packageManager: null,
|
|
127
|
+
source: bunBlockedByMissingNode ? "missing-node" : (availablePackageManagers.length > 0 ? "unsupported" : "missing")
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function buildCliToolInstallCommand(packageManager, { packageName, skipScripts = false }) {
|
|
132
|
+
if (packageManager === "npm") {
|
|
133
|
+
return {
|
|
134
|
+
command: "npm",
|
|
135
|
+
args: [
|
|
136
|
+
"install",
|
|
137
|
+
"-g",
|
|
138
|
+
...(skipScripts ? ["--ignore-scripts"] : []),
|
|
139
|
+
packageName,
|
|
140
|
+
"--force"
|
|
141
|
+
]
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (packageManager === "bun") {
|
|
145
|
+
return {
|
|
146
|
+
command: "bun",
|
|
147
|
+
args: [
|
|
148
|
+
"install",
|
|
149
|
+
"-g",
|
|
150
|
+
...(skipScripts ? ["--ignore-scripts"] : []),
|
|
151
|
+
packageName
|
|
152
|
+
]
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
throw new Error(`Unsupported package manager: ${packageManager}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function getPackageManagerInstallHelp(platform = getPlatform()) {
|
|
159
|
+
const platformLabel = {
|
|
160
|
+
darwin: "macOS",
|
|
161
|
+
win32: "Windows",
|
|
162
|
+
linux: "Linux"
|
|
163
|
+
}[platform] || platform;
|
|
164
|
+
return {
|
|
165
|
+
platformLabel,
|
|
166
|
+
mainlandUrl: "https://npmmirror.com/mirrors/node/",
|
|
167
|
+
officialUrl: "https://nodejs.org/en/download/"
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getAvailablePackageManagers() {
|
|
172
|
+
return ["bun", "npm"].filter((packageManager) => commandExists(packageManager));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function getBunGlobalBinDir(availablePackageManagers = getAvailablePackageManagers()) {
|
|
176
|
+
if (!availablePackageManagers.includes("bun")) {
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
return readCommandOutput("bun", ["pm", "bin", "-g"]) || join(home, ".bun", "bin");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function getNpmGlobalPrefix(availablePackageManagers = getAvailablePackageManagers()) {
|
|
183
|
+
if (!availablePackageManagers.includes("npm")) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
return readCommandOutput("npm", ["prefix", "-g"]);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function installCliTool(tool, { confirmOrCancel }) {
|
|
190
|
+
const toolConfig = {
|
|
191
|
+
claude: {
|
|
192
|
+
label: "Claude Code",
|
|
193
|
+
command: "claude",
|
|
194
|
+
packageName: "@anthropic-ai/claude-code",
|
|
195
|
+
supportedPackageManagers: ["npm"],
|
|
196
|
+
installRequirement: "Claude Code 安装需要执行 postinstall;Bun 默认会阻止该脚本,因此需使用 npm。"
|
|
197
|
+
},
|
|
198
|
+
codex: {
|
|
199
|
+
label: "Codex",
|
|
200
|
+
command: "codex",
|
|
201
|
+
packageName: "@openai/codex"
|
|
202
|
+
},
|
|
203
|
+
pi: {
|
|
204
|
+
label: "Pi",
|
|
205
|
+
command: "pi",
|
|
206
|
+
packageName: "@earendil-works/pi-coding-agent",
|
|
207
|
+
skipScripts: true
|
|
208
|
+
}
|
|
209
|
+
}[tool];
|
|
210
|
+
|
|
211
|
+
if (!toolConfig) {
|
|
212
|
+
throw new Error(`Unsupported tool: ${tool}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const commandPath = getCommandPath(toolConfig.command);
|
|
216
|
+
const installed = Boolean(commandPath);
|
|
217
|
+
const availablePackageManagers = getAvailablePackageManagers();
|
|
218
|
+
const packageManagerChoice = chooseCliInstallPackageManager({
|
|
219
|
+
commandPath,
|
|
220
|
+
availablePackageManagers,
|
|
221
|
+
bunGlobalBinDir: getBunGlobalBinDir(availablePackageManagers),
|
|
222
|
+
npmGlobalPrefix: getNpmGlobalPrefix(availablePackageManagers),
|
|
223
|
+
platform: getPlatform(),
|
|
224
|
+
nodeAvailable: commandExists("node"),
|
|
225
|
+
supportedPackageManagers: toolConfig.supportedPackageManagers
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
if (!packageManagerChoice.packageManager) {
|
|
229
|
+
const help = getPackageManagerInstallHelp();
|
|
230
|
+
p.log.warn(`未检测到可用于安装 ${toolConfig.label} 的包管理器。`);
|
|
231
|
+
if (packageManagerChoice.source === "missing-node") {
|
|
232
|
+
p.log.message(`${toolConfig.label} 是 Node CLI;使用 Bun 安装前也需要先安装 Node.js。`);
|
|
233
|
+
}
|
|
234
|
+
if (toolConfig.installRequirement) {
|
|
235
|
+
p.log.message(toolConfig.installRequirement);
|
|
236
|
+
}
|
|
237
|
+
p.log.message(`${help.platformLabel} 可先安装 Node.js/npm,再重新运行安装。`);
|
|
238
|
+
p.log.message(`中国大陆镜像: ${help.mainlandUrl}`);
|
|
239
|
+
p.log.message(`官方下载页: ${help.officialUrl}`);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (installed) {
|
|
244
|
+
const managerMessage = packageManagerChoice.source === "existing"
|
|
245
|
+
? `检测到原安装方式为 ${packageManagerChoice.packageManager}`
|
|
246
|
+
: `未识别原安装方式,将使用 ${packageManagerChoice.packageManager}`;
|
|
247
|
+
const shouldUpdate = await confirmOrCancel({
|
|
248
|
+
message: `${toolConfig.label} 已检测到(${managerMessage}),是否继续安装/更新?`,
|
|
249
|
+
initialValue: false
|
|
250
|
+
});
|
|
251
|
+
if (!shouldUpdate) {
|
|
252
|
+
p.log.message(`跳过 ${toolConfig.label} 安装。`);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const installCommand = buildCliToolInstallCommand(packageManagerChoice.packageManager, toolConfig);
|
|
258
|
+
const s = p.spinner();
|
|
259
|
+
s.start(`正在使用 ${packageManagerChoice.packageManager} 安装 ${toolConfig.label}...`);
|
|
260
|
+
try {
|
|
261
|
+
await runCommand(installCommand.command, installCommand.args);
|
|
262
|
+
s.stop(`${toolConfig.label} 安装完成`);
|
|
263
|
+
} catch (e) {
|
|
264
|
+
s.cancel(c.red(`${toolConfig.label} 安装失败: ${e.message}`));
|
|
265
|
+
throw e;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export {
|
|
270
|
+
buildCliToolInstallCommand,
|
|
271
|
+
chooseCliInstallPackageManager,
|
|
272
|
+
getPackageManagerInstallHelp,
|
|
273
|
+
getRunCommandSpawnOptions,
|
|
274
|
+
inferPackageManagerFromCommandPath,
|
|
275
|
+
installCliTool,
|
|
276
|
+
commandExists
|
|
277
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abelworkflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-rc.1",
|
|
4
4
|
"description": "Install AbelWorkflow into ~/.agents and create Claude/Codex symlinks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "
|
|
8
|
-
"test:
|
|
7
|
+
"test": "npm run test:node",
|
|
8
|
+
"test:node": "node --test test/*.test.mjs",
|
|
9
|
+
"test:python": "python -m unittest discover -s test",
|
|
10
|
+
"test:dev-browser": "npm test --prefix skills/dev-browser",
|
|
11
|
+
"test:contracts": "node --test test/runtime-doc-contracts.test.mjs test/cli-args.test.mjs",
|
|
12
|
+
"typecheck": "npm run typecheck --prefix skills/dev-browser",
|
|
13
|
+
"build": "npm run build --prefix skills/dev-browser",
|
|
14
|
+
"prepack": "npm run build",
|
|
15
|
+
"check:docs": "node --test test/docs-contracts.test.mjs test/runtime-doc-contracts.test.mjs",
|
|
16
|
+
"check:package": "node --test test/package-contents.test.mjs",
|
|
17
|
+
"check": "npm run build && npm run test:node && npm run test:python && npm run test:dev-browser && npm run typecheck && npm run check:docs && npm run check:package"
|
|
9
18
|
},
|
|
10
19
|
"bin": {
|
|
11
20
|
"abelworkflow": "bin/abelworkflow.mjs"
|
|
@@ -13,21 +22,45 @@
|
|
|
13
22
|
"files": [
|
|
14
23
|
"bin",
|
|
15
24
|
"lib",
|
|
16
|
-
"AGENTS.md",
|
|
17
25
|
"README.md",
|
|
18
|
-
"commands",
|
|
19
|
-
"skills",
|
|
20
26
|
"extensions",
|
|
21
|
-
"
|
|
22
|
-
".
|
|
27
|
+
"skills/context7-auto-research/.env.example",
|
|
28
|
+
"skills/context7-auto-research/SKILL.md",
|
|
29
|
+
"skills/context7-auto-research/context7-api.cjs",
|
|
30
|
+
"skills/dev-browser/SKILL.md",
|
|
31
|
+
"skills/dev-browser/dist",
|
|
32
|
+
"skills/dev-browser/package-lock.json",
|
|
33
|
+
"skills/dev-browser/package.json",
|
|
34
|
+
"skills/dev-browser/references",
|
|
35
|
+
"skills/git-commit/SKILL.md",
|
|
36
|
+
"skills/grok-search/.env.example",
|
|
37
|
+
"skills/grok-search/SKILL.md",
|
|
38
|
+
"skills/grok-search/defaults.json",
|
|
39
|
+
"skills/grok-search/gitignore.template",
|
|
40
|
+
"skills/grok-search/requirements.txt",
|
|
41
|
+
"skills/grok-search/scripts/_dotenv.py",
|
|
42
|
+
"skills/grok-search/scripts/groksearch_cli.py",
|
|
43
|
+
"skills/grok-search/scripts/groksearch_entry.py",
|
|
44
|
+
"skills/prompt-enhancer/.env.example",
|
|
45
|
+
"skills/prompt-enhancer/ADVANCED.md",
|
|
46
|
+
"skills/prompt-enhancer/SKILL.md",
|
|
47
|
+
"skills/prompt-enhancer/TEMPLATE.md",
|
|
48
|
+
"skills/prompt-enhancer/requirements.txt",
|
|
49
|
+
"skills/prompt-enhancer/scripts/_dotenv.py",
|
|
50
|
+
"skills/prompt-enhancer/scripts/enhance.py",
|
|
51
|
+
"skills/prompt-enhancer/scripts/prompt_enhancer_entry.py",
|
|
52
|
+
"skills/time/SKILL.md",
|
|
53
|
+
"skills/time/scripts/time_cli.py"
|
|
23
54
|
],
|
|
24
55
|
"engines": {
|
|
25
|
-
"node": ">=
|
|
56
|
+
"node": ">=22"
|
|
26
57
|
},
|
|
58
|
+
"packageManager": "npm@10.9.2",
|
|
27
59
|
"license": "MIT",
|
|
28
60
|
"dependencies": {
|
|
29
61
|
"@clack/prompts": "^1.2.0",
|
|
30
62
|
"picocolors": "^1.1.1",
|
|
31
|
-
"proper-lockfile": "4.1.2"
|
|
63
|
+
"proper-lockfile": "4.1.2",
|
|
64
|
+
"smol-toml": "1.7.0"
|
|
32
65
|
}
|
|
33
66
|
}
|
|
@@ -30,13 +30,13 @@ Common cues:
|
|
|
30
30
|
|
|
31
31
|
## Workflow
|
|
32
32
|
|
|
33
|
-
1. Run from this skill directory and use `./context7-api.
|
|
33
|
+
1. Run from this skill directory and use `./context7-api.cjs`.
|
|
34
34
|
2. Search with the full user query:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
cd skills/context7-auto-research
|
|
38
|
-
node ./context7-api.
|
|
39
|
-
node ./context7-api.
|
|
38
|
+
node ./context7-api.cjs --help
|
|
39
|
+
node ./context7-api.cjs search '<library-name>' - <<'__C7_QUERY__'
|
|
40
40
|
<full user query>
|
|
41
41
|
__C7_QUERY__
|
|
42
42
|
```
|
|
@@ -50,7 +50,7 @@ __C7_QUERY__
|
|
|
50
50
|
4. Fetch focused documentation:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
node ./context7-api.
|
|
53
|
+
node ./context7-api.cjs context '<library-id>' - <<'__C7_QUERY__'
|
|
54
54
|
<feature name or focused question>
|
|
55
55
|
__C7_QUERY__
|
|
56
56
|
```
|
|
@@ -72,7 +72,7 @@ __C7_QUERY__
|
|
|
72
72
|
|
|
73
73
|
- Preferred: `CONTEXT7_API_KEY` environment variable
|
|
74
74
|
- Also supported: `<skill-dir>/.env`
|
|
75
|
-
- CLI help: `node ./context7-api.
|
|
75
|
+
- CLI help: `node ./context7-api.cjs --help`
|
|
76
76
|
|
|
77
77
|
## Notes
|
|
78
78
|
|
|
@@ -44,12 +44,12 @@ function printErrorResult(commandName, error, exitCode = 1) {
|
|
|
44
44
|
|
|
45
45
|
function printUsage() {
|
|
46
46
|
console.error(`Usage:
|
|
47
|
-
context7-api.
|
|
48
|
-
context7-api.
|
|
47
|
+
context7-api.cjs search <libraryName> <query|->
|
|
48
|
+
context7-api.cjs context <libraryId> <query|->
|
|
49
49
|
|
|
50
50
|
Examples:
|
|
51
|
-
node context7-api.
|
|
52
|
-
node context7-api.
|
|
51
|
+
node context7-api.cjs search react "useEffect cleanup"
|
|
52
|
+
node context7-api.cjs context /facebook/react -
|
|
53
53
|
|
|
54
54
|
Config:
|
|
55
55
|
CONTEXT7_API_KEY from environment, or .env in the script directory`);
|
|
@@ -83,10 +83,7 @@ function loadApiKey() {
|
|
|
83
83
|
if (key !== 'CONTEXT7_API_KEY') {
|
|
84
84
|
continue;
|
|
85
85
|
}
|
|
86
|
-
|
|
87
|
-
if (value) {
|
|
88
|
-
return value.replace(/^["']|["']$/g, '');
|
|
89
|
-
}
|
|
86
|
+
return trimmed.slice(separatorIndex + 1).trim().replace(/^["']|["']$/g, '');
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
return null;
|