adaptive-director-skill 0.1.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 +105 -36
- package/package.json +8 -6
- package/scripts/cli.mjs +55 -0
- package/scripts/discover.mjs +22 -9
- package/scripts/doctor.mjs +141 -0
- package/scripts/install.mjs +97 -0
- package/scripts/refresh.mjs +62 -0
- package/scripts/setup.mjs +149 -123
- package/scripts/smoke-test.mjs +138 -89
- package/{SKILL.md → skills/adaptive-director/SKILL.md} +11 -11
- package/skills/adaptive-director/data/registry.json +50 -0
- package/skills/adaptive-director/examples/clean-run-walkthrough.md +83 -0
- package/skills/adaptive-director/examples/critical-fix-cycle-walkthrough.md +70 -0
- package/{references → skills/adaptive-director/references}/capability-registry.md +17 -10
- package/{scripts → skills/adaptive-director/scripts}/route.mjs +30 -21
- package/skills/adaptive-director/templates/fix-brief.md +27 -0
- package/skills/adaptive-director/templates/implement-brief.md +28 -0
- package/skills/adaptive-director/templates/plan-brief.md +31 -0
- package/skills/adaptive-director/templates/review-brief.md +42 -0
- package/skills/adaptive-director/templates/verify-brief.md +28 -0
- package/data/registry.json +0 -42
- /package/{references → skills/adaptive-director/references}/delegate-integration.md +0 -0
- /package/{references → skills/adaptive-director/references}/handoff-schema.md +0 -0
- /package/{references → skills/adaptive-director/references}/routing-rules.md +0 -0
- /package/{scripts → skills/adaptive-director/scripts}/resume.mjs +0 -0
- /package/{scripts → skills/adaptive-director/scripts}/run-state.mjs +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/adaptive-director-skill)
|
|
4
4
|
[](https://nodejs.org)
|
|
5
|
-
[-blue.svg)](#
|
|
5
|
+
[-blue.svg)](#core-principles)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
8
|
> **One task in. The right agents take it from there.**
|
|
@@ -59,31 +59,59 @@ flowchart LR
|
|
|
59
59
|
|
|
60
60
|
Adaptive Director runs with **zero external npm dependencies** (pure Node.js built-ins).
|
|
61
61
|
|
|
62
|
-
### 1. Install
|
|
62
|
+
### 1. Install Globally
|
|
63
63
|
|
|
64
|
-
Via npm:
|
|
65
64
|
```bash
|
|
66
|
-
npm install adaptive-director-skill
|
|
65
|
+
npm install -g adaptive-director-skill
|
|
67
66
|
```
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
### 2. Set Up
|
|
69
|
+
|
|
70
|
+
> `adaptive-director setup` registers the Skill with your coding-agent hosts, discovers available agents, detects optional delegate-skills integration, and creates the local Adaptive Director configuration.
|
|
71
|
+
|
|
70
72
|
```bash
|
|
71
|
-
|
|
72
|
-
cd Adaptive-Orchestrator
|
|
73
|
+
adaptive-director setup
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
Or without a global install:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npx adaptive-director-skill setup
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 3. Verify
|
|
83
|
+
|
|
76
84
|
```bash
|
|
77
|
-
|
|
78
|
-
node scripts/smoke-test.mjs
|
|
85
|
+
adaptive-director doctor
|
|
79
86
|
```
|
|
80
87
|
|
|
81
|
-
|
|
88
|
+
Expected output:
|
|
89
|
+
```
|
|
90
|
+
✓ Package installed
|
|
91
|
+
✓ Skill source exists
|
|
92
|
+
✓ SKILL.md exists
|
|
93
|
+
✓ references/ exists
|
|
94
|
+
✓ templates/ exists
|
|
95
|
+
✓ examples/ exists
|
|
96
|
+
✓ Registry exists
|
|
97
|
+
✓ Registry valid
|
|
98
|
+
✓ Config exists
|
|
99
|
+
✓ Config valid
|
|
100
|
+
✓ Routing script works
|
|
101
|
+
✓ Run state script exists
|
|
102
|
+
✓ Resume script exists
|
|
103
|
+
✓ codex detected
|
|
104
|
+
✓ Skill installed for codex
|
|
105
|
+
|
|
106
|
+
Ready.
|
|
107
|
+
```
|
|
82
108
|
|
|
83
|
-
|
|
109
|
+
### 4. Run with Your AI Agent
|
|
110
|
+
|
|
111
|
+
The Skill is now installed in your agent's skills directory. Prompt your agent:
|
|
84
112
|
|
|
85
113
|
```text
|
|
86
|
-
Use $adaptive-director
|
|
114
|
+
Use $adaptive-director to implement Stripe checkout in Flutter
|
|
87
115
|
```
|
|
88
116
|
|
|
89
117
|
---
|
|
@@ -103,33 +131,50 @@ Use $adaptive-director-skill to implement Stripe checkout in Flutter
|
|
|
103
131
|
|
|
104
132
|
---
|
|
105
133
|
|
|
106
|
-
## Architecture
|
|
134
|
+
## Repository Architecture
|
|
135
|
+
|
|
136
|
+
The repository separates the **npm management/installer layer** from the **self-contained Agent Skill**:
|
|
107
137
|
|
|
108
|
-
|
|
138
|
+
- **Repository Root:** npm distribution, CLI tools, setup, host discovery, and health diagnostics (`scripts/`).
|
|
139
|
+
- **`skills/adaptive-director/`:** The canonical, portable Agent Skill (procedural brain, runtime scripts, templates, references, and registry data).
|
|
109
140
|
|
|
110
141
|
```text
|
|
111
|
-
|
|
112
|
-
├──
|
|
113
|
-
├──
|
|
114
|
-
├──
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
142
|
+
Adaptive-Director-Skill/
|
|
143
|
+
├── scripts/ # Management & CLI layer
|
|
144
|
+
│ ├── cli.mjs # Main CLI router
|
|
145
|
+
│ ├── setup.mjs # Interactive host setup
|
|
146
|
+
│ ├── install.mjs # Idempotent skill copier
|
|
147
|
+
│ ├── refresh.mjs # Safe config refresher
|
|
148
|
+
│ ├── discover.mjs # Local agent discovery
|
|
149
|
+
│ ├── doctor.mjs # Installation diagnostics
|
|
150
|
+
│ └── smoke-test.mjs # Automated test suite
|
|
151
|
+
│
|
|
152
|
+
└── skills/adaptive-director/ # Portable Agent Skill (the brain)
|
|
153
|
+
├── SKILL.md # Procedural runbook
|
|
154
|
+
├── scripts/ # Runtime scripts (route, run-state, resume)
|
|
155
|
+
├── references/ # Deep documentation & schemas
|
|
156
|
+
├── templates/ # Standardized phase brief templates
|
|
157
|
+
├── examples/ # Realistic execution walkthroughs
|
|
158
|
+
└── data/ # Capability registry
|
|
120
159
|
```
|
|
121
160
|
|
|
122
|
-
|
|
161
|
+
---
|
|
123
162
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
163
|
+
## CLI Commands
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
adaptive-director setup # Interactive: discover hosts, install Skill, create config
|
|
167
|
+
adaptive-director install # Re-install/update Skill in host directories
|
|
168
|
+
adaptive-director refresh # Re-discover hosts & update config (preserves overrides)
|
|
169
|
+
adaptive-director doctor # Validate installation and health
|
|
170
|
+
adaptive-director help # Show usage
|
|
171
|
+
```
|
|
128
172
|
|
|
129
173
|
---
|
|
130
174
|
|
|
131
175
|
## Core Principles
|
|
132
176
|
|
|
177
|
+
- **Routing Priority:** User overrides → Delegate fleet lanes → Capability registry → Default fallback.
|
|
133
178
|
- **Independent Review:** The coder never reviews its own work.
|
|
134
179
|
- **Max Reasoning Opt-in:** `max` effort is locked by default; requires `--allow-max`.
|
|
135
180
|
- **Runaway Loop Protection:** Maximum 1 automated fix cycle before alerting the user.
|
|
@@ -138,19 +183,43 @@ adaptive-director/
|
|
|
138
183
|
|
|
139
184
|
---
|
|
140
185
|
|
|
141
|
-
## Configuration (`~/.adaptive-director/config.
|
|
186
|
+
## Configuration (`~/.adaptive-director/config.json`)
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"version": 1,
|
|
191
|
+
"defaultBudget": "balanced",
|
|
192
|
+
"overrides": {
|
|
193
|
+
"plan": "claude",
|
|
194
|
+
"implement": "codex"
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
142
200
|
|
|
143
|
-
|
|
144
|
-
defaultBudget: balanced # conservative | balanced | quality
|
|
201
|
+
## Upgrading
|
|
145
202
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
203
|
+
After a package upgrade, re-install the Skill into your host environments:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npm install -g adaptive-director-skill@latest
|
|
207
|
+
adaptive-director install
|
|
208
|
+
adaptive-director doctor
|
|
150
209
|
```
|
|
151
210
|
|
|
152
211
|
---
|
|
153
212
|
|
|
213
|
+
## Uninstalling
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
npm uninstall -g adaptive-director-skill
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
> **Note:** npm uninstall removes the package, but does **not** remove Skill copies that were installed into your coding-agent host directories. To clean those up, manually delete the `Adaptive-Director/` folder from each host skill directory (e.g. `~/.codex/skills/Adaptive-Director/`).
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
154
223
|
## License
|
|
155
224
|
|
|
156
225
|
MIT License © 2026 [Ahmed Tamer](https://github.com/tamourax). See [LICENSE](LICENSE) for details.
|
package/package.json
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adaptive-director-skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Adaptive Director Skill — Skill-first adaptive multi-agent orchestration for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"adaptive-director": "scripts/cli.mjs"
|
|
8
|
+
},
|
|
6
9
|
"license": "MIT",
|
|
7
10
|
"author": "Ahmed Tamer",
|
|
8
11
|
"repository": {
|
|
9
12
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/tamourax/Adaptive-
|
|
13
|
+
"url": "git+https://github.com/tamourax/Adaptive-Director-Skill.git"
|
|
11
14
|
},
|
|
12
15
|
"files": [
|
|
13
|
-
"SKILL.md",
|
|
14
16
|
"README.md",
|
|
15
17
|
"LICENSE",
|
|
16
18
|
"scripts/",
|
|
17
|
-
"
|
|
18
|
-
"data/"
|
|
19
|
+
"skills/"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
21
22
|
"test": "node scripts/smoke-test.mjs",
|
|
22
23
|
"setup": "node scripts/setup.mjs",
|
|
23
|
-
"discover": "node scripts/discover.mjs"
|
|
24
|
+
"discover": "node scripts/discover.mjs",
|
|
25
|
+
"doctor": "node scripts/doctor.mjs"
|
|
24
26
|
},
|
|
25
27
|
"keywords": [
|
|
26
28
|
"ai",
|
package/scripts/cli.mjs
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const command = args[0] || 'help';
|
|
12
|
+
|
|
13
|
+
const commands = {
|
|
14
|
+
setup: 'setup.mjs',
|
|
15
|
+
install: 'install.mjs',
|
|
16
|
+
refresh: 'refresh.mjs',
|
|
17
|
+
doctor: 'doctor.mjs',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
if (command === 'help' || command === '--help' || command === '-h') {
|
|
21
|
+
console.log(`Adaptive Director Skill CLI v1.0.0
|
|
22
|
+
|
|
23
|
+
Usage:
|
|
24
|
+
adaptive-director <command>
|
|
25
|
+
|
|
26
|
+
Commands:
|
|
27
|
+
setup - Initial interactive setup and installation
|
|
28
|
+
install - Install/copy the Skill into supported host skill directories
|
|
29
|
+
refresh - Re-run discovery and update config without destroying user overrides
|
|
30
|
+
doctor - Validate installation and report health
|
|
31
|
+
help - Show this help message
|
|
32
|
+
`);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const targetScript = commands[command];
|
|
37
|
+
|
|
38
|
+
if (!targetScript) {
|
|
39
|
+
console.error(`Unknown command: ${command}`);
|
|
40
|
+
console.log(`Run 'adaptive-director help' for usage.`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const scriptPath = path.join(__dirname, targetScript);
|
|
45
|
+
|
|
46
|
+
if (!fs.existsSync(scriptPath)) {
|
|
47
|
+
console.error(`Command not yet implemented: ${command}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const result = spawnSync('node', [scriptPath, ...args.slice(1)], {
|
|
52
|
+
stdio: 'inherit'
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
process.exit(result.status ?? 1);
|
package/scripts/discover.mjs
CHANGED
|
@@ -20,15 +20,15 @@ import { homedir } from 'node:os'
|
|
|
20
20
|
// ─── Known agents ─────────────────────────────────────────────────────────────
|
|
21
21
|
|
|
22
22
|
const KNOWN_AGENTS = [
|
|
23
|
-
{ id: 'claude', bins: ['claude'], versionArgs: ['--version'] },
|
|
24
|
-
{ id: 'codex', bins: ['codex'], versionArgs: ['--version'] },
|
|
25
|
-
{ id: 'agy', bins: ['agy'], versionArgs: ['--version'] },
|
|
26
|
-
{ id: 'gemini', bins: ['gemini'], versionArgs: ['--version'] },
|
|
27
|
-
{ id: 'opencode', bins: ['opencode'], versionArgs: ['--version'] },
|
|
28
|
-
{ id: 'aider', bins: ['aider'], versionArgs: ['--version'] },
|
|
29
|
-
{ id: 'cursor', bins: ['cursor-agent'], versionArgs: ['--version'] },
|
|
30
|
-
{ id: 'cline', bins: ['cline'], versionArgs: ['--version'] },
|
|
31
|
-
{ id: 'copilot', bins: ['copilot'], versionArgs: ['--version'] },
|
|
23
|
+
{ id: 'claude', bins: ['claude'], versionArgs: ['--version'], skillPaths: ['.claude/skills', '.config/claude/skills'] },
|
|
24
|
+
{ id: 'codex', bins: ['codex'], versionArgs: ['--version'], skillPaths: ['.codex/skills'] },
|
|
25
|
+
{ id: 'agy', bins: ['agy'], versionArgs: ['--version'], skillPaths: ['.gemini/antigravity/builtin/skills', '.gemini/antigravity/skills', '.gemini/antigravity-ide/skills'] },
|
|
26
|
+
{ id: 'gemini', bins: ['gemini'], versionArgs: ['--version'], skillPaths: ['.gemini/skills'] },
|
|
27
|
+
{ id: 'opencode', bins: ['opencode'], versionArgs: ['--version'], skillPaths: ['.opencode/skills'] },
|
|
28
|
+
{ id: 'aider', bins: ['aider'], versionArgs: ['--version'], skillPaths: ['.aider/skills'] },
|
|
29
|
+
{ id: 'cursor', bins: ['cursor-agent'], versionArgs: ['--version'], skillPaths: ['.cursor/skills'] },
|
|
30
|
+
{ id: 'cline', bins: ['cline'], versionArgs: ['--version'], skillPaths: ['.cline/skills'] },
|
|
31
|
+
{ id: 'copilot', bins: ['copilot'], versionArgs: ['--version'], skillPaths: ['.copilot/skills'] },
|
|
32
32
|
]
|
|
33
33
|
|
|
34
34
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
@@ -116,10 +116,23 @@ function discover() {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
const version = getVersion(bin, desc.versionArgs)
|
|
119
|
+
let detectedSkillPath = null
|
|
120
|
+
if (desc.skillPaths) {
|
|
121
|
+
for (const sp of desc.skillPaths) {
|
|
122
|
+
const fullPath = join(homedir(), sp)
|
|
123
|
+
if (existsSync(fullPath)) {
|
|
124
|
+
detectedSkillPath = fullPath
|
|
125
|
+
break
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
119
130
|
agents[desc.id] = {
|
|
120
131
|
installed: true,
|
|
121
132
|
available: version !== null,
|
|
122
133
|
version: version ?? 'unknown',
|
|
134
|
+
skillPath: detectedSkillPath,
|
|
135
|
+
hasSkill: detectedSkillPath ? existsSync(join(detectedSkillPath, 'adaptive-director')) || existsSync(join(detectedSkillPath, 'Adaptive-Director')) || existsSync(join(detectedSkillPath, 'adaptive-director-skill')) : false
|
|
123
136
|
}
|
|
124
137
|
}
|
|
125
138
|
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFileSync } from 'node:child_process';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { join, dirname } from 'node:path';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
function run(script, args = []) {
|
|
11
|
+
try {
|
|
12
|
+
const out = execFileSync(process.execPath, [script, ...args], {
|
|
13
|
+
encoding: 'utf8', timeout: 15000,
|
|
14
|
+
cwd: process.cwd(),
|
|
15
|
+
});
|
|
16
|
+
return JSON.parse(out.trim());
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function check(label, condition, fix = null) {
|
|
23
|
+
if (condition) {
|
|
24
|
+
console.log(`✓ ${label}`);
|
|
25
|
+
return true;
|
|
26
|
+
} else {
|
|
27
|
+
console.log(`✗ ${label}`);
|
|
28
|
+
if (fix) console.log(` Fix: ${fix}`);
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function warn(label) {
|
|
34
|
+
console.log(`! ${label}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const configDir = join(homedir(), '.adaptive-director');
|
|
38
|
+
const configPath = join(configDir, 'config.json');
|
|
39
|
+
const pkgRoot = join(__dirname, '..');
|
|
40
|
+
const skillRoot = join(pkgRoot, 'skills', 'adaptive-director');
|
|
41
|
+
|
|
42
|
+
console.log('Adaptive Director Doctor\n');
|
|
43
|
+
|
|
44
|
+
let allGood = true;
|
|
45
|
+
|
|
46
|
+
// ── Package & Skill files ──────────────────────────────────────────────────
|
|
47
|
+
allGood &= check('Package installed', existsSync(join(pkgRoot, 'package.json')));
|
|
48
|
+
allGood &= check('Skill source exists', existsSync(skillRoot));
|
|
49
|
+
allGood &= check('SKILL.md exists', existsSync(join(skillRoot, 'SKILL.md')));
|
|
50
|
+
allGood &= check('references/ exists', existsSync(join(skillRoot, 'references')));
|
|
51
|
+
allGood &= check('templates/ exists', existsSync(join(skillRoot, 'templates')));
|
|
52
|
+
allGood &= check('examples/ exists', existsSync(join(skillRoot, 'examples')));
|
|
53
|
+
|
|
54
|
+
// ── Registry ──────────────────────────────────────────────────────────────
|
|
55
|
+
const registryPath = join(skillRoot, 'data', 'registry.json');
|
|
56
|
+
if (check('Registry exists', existsSync(registryPath))) {
|
|
57
|
+
try {
|
|
58
|
+
JSON.parse(readFileSync(registryPath, 'utf8'));
|
|
59
|
+
check('Registry valid', true);
|
|
60
|
+
} catch {
|
|
61
|
+
allGood &= check('Registry valid', false, 'Reinstall package');
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
allGood = false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ── Config ────────────────────────────────────────────────────────────────
|
|
68
|
+
if (check('Config exists', existsSync(configPath), 'adaptive-director setup')) {
|
|
69
|
+
try {
|
|
70
|
+
JSON.parse(readFileSync(configPath, 'utf8'));
|
|
71
|
+
check('Config valid', true);
|
|
72
|
+
} catch {
|
|
73
|
+
allGood &= check('Config valid', false, 'rm ~/.adaptive-director/config.json && adaptive-director setup');
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
allGood = false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ── Runtime Skill Scripts ─────────────────────────────────────────────────
|
|
80
|
+
const routePath = join(skillRoot, 'scripts', 'route.mjs');
|
|
81
|
+
if (existsSync(routePath)) {
|
|
82
|
+
try {
|
|
83
|
+
const testPayload = JSON.stringify({ taskSize: 'small', phase: 'implement', budget: 'balanced', allowMax: false, delegateEnabled: false });
|
|
84
|
+
const out = execFileSync(process.execPath, [routePath, '--input', testPayload], {
|
|
85
|
+
encoding: 'utf8', timeout: 8000
|
|
86
|
+
});
|
|
87
|
+
const result = JSON.parse(out.trim());
|
|
88
|
+
const valid = result && result.agent && result.effort && result.execution;
|
|
89
|
+
allGood &= check('Routing script works', valid, 'Check Node version or reinstall');
|
|
90
|
+
} catch (e) {
|
|
91
|
+
allGood &= check('Routing script works', false, `Error: ${e.message}`);
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
allGood &= check('Routing script works', false, 'Script missing in skills/adaptive-director/scripts — reinstall package');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
allGood &= check('Run state script exists', existsSync(join(skillRoot, 'scripts', 'run-state.mjs')));
|
|
98
|
+
allGood &= check('Resume script exists', existsSync(join(skillRoot, 'scripts', 'resume.mjs')));
|
|
99
|
+
|
|
100
|
+
// ── Host discovery ────────────────────────────────────────────────────────
|
|
101
|
+
console.log('');
|
|
102
|
+
const discovery = run(join(__dirname, 'discover.mjs'));
|
|
103
|
+
if (discovery) {
|
|
104
|
+
let anyHost = false;
|
|
105
|
+
for (const [id, info] of Object.entries(discovery.agents ?? {})) {
|
|
106
|
+
if (!info.installed) continue;
|
|
107
|
+
anyHost = true;
|
|
108
|
+
check(`${id} detected`, true);
|
|
109
|
+
const hostHasSkill = info.skillPath && (
|
|
110
|
+
existsSync(join(info.skillPath, 'adaptive-director', 'SKILL.md')) ||
|
|
111
|
+
existsSync(join(info.skillPath, 'Adaptive-Director', 'SKILL.md'))
|
|
112
|
+
);
|
|
113
|
+
if (hostHasSkill) {
|
|
114
|
+
check(`Skill installed for ${id}`, true);
|
|
115
|
+
} else if (info.skillPath) {
|
|
116
|
+
allGood &= check(`Skill installed for ${id}`, false,
|
|
117
|
+
`adaptive-director install ${info.skillPath}`);
|
|
118
|
+
} else {
|
|
119
|
+
warn(`Skill for ${id}: skill directory unknown (run setup after configuring host)`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (!anyHost) warn('No supported hosts detected');
|
|
123
|
+
|
|
124
|
+
console.log('');
|
|
125
|
+
const ds = discovery.delegateSkills ?? { installed: false };
|
|
126
|
+
if (ds.installed) {
|
|
127
|
+
check(`delegate-skills detected (${Object.keys(ds.lanes ?? {}).length} lane(s))`, true);
|
|
128
|
+
} else {
|
|
129
|
+
warn('delegate-skills not detected (optional)');
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
allGood &= check('Discovery script works', false, 'Check Node version or reinstall');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
console.log('');
|
|
136
|
+
if (allGood) {
|
|
137
|
+
console.log('Ready.');
|
|
138
|
+
} else {
|
|
139
|
+
console.log('Some checks failed. Run "adaptive-director setup" to fix.');
|
|
140
|
+
process.exitCode = 1;
|
|
141
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFileSync } from 'node:child_process';
|
|
3
|
+
import { mkdirSync, cpSync, rmSync, existsSync } from 'node:fs';
|
|
4
|
+
import { join, dirname } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const projectRoot = join(__dirname, '..');
|
|
9
|
+
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const targets = args.filter(a => !a.startsWith('-'));
|
|
12
|
+
|
|
13
|
+
const canonicalSkillSource = join(projectRoot, 'skills', 'adaptive-director');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Copy Adaptive Director Skill files into a host skill directory.
|
|
17
|
+
* Idempotent: removes old copy first, then copies fresh from skills/adaptive-director.
|
|
18
|
+
*/
|
|
19
|
+
function installInto(hostSkillDir) {
|
|
20
|
+
const dest = join(hostSkillDir, 'adaptive-director');
|
|
21
|
+
console.log(` Installing into ${dest}...`);
|
|
22
|
+
if (!existsSync(canonicalSkillSource)) {
|
|
23
|
+
console.error(` Error: Canonical skill source not found at ${canonicalSkillSource}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
// Remove legacy title-case folder if different and present
|
|
27
|
+
const legacyDest = join(hostSkillDir, 'Adaptive-Director');
|
|
28
|
+
if (legacyDest.toLowerCase() === dest.toLowerCase() && existsSync(legacyDest)) {
|
|
29
|
+
rmSync(legacyDest, { recursive: true, force: true });
|
|
30
|
+
} else if (existsSync(dest)) {
|
|
31
|
+
rmSync(dest, { recursive: true, force: true });
|
|
32
|
+
}
|
|
33
|
+
mkdirSync(dest, { recursive: true });
|
|
34
|
+
cpSync(canonicalSkillSource, dest, { recursive: true });
|
|
35
|
+
console.log(` ✓ Installed successfully at ${dest}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ─── If paths were passed as arguments, install into those directly ─────────
|
|
39
|
+
if (targets.length > 0) {
|
|
40
|
+
for (const target of targets) {
|
|
41
|
+
installInto(target);
|
|
42
|
+
}
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─── No args: auto-discover hosts and install ───────────────────────────────
|
|
47
|
+
const discoverScript = join(__dirname, 'discover.mjs');
|
|
48
|
+
|
|
49
|
+
function runDiscover() {
|
|
50
|
+
try {
|
|
51
|
+
const out = execFileSync(process.execPath, [discoverScript], {
|
|
52
|
+
encoding: 'utf8', timeout: 15000, cwd: process.cwd(),
|
|
53
|
+
});
|
|
54
|
+
return JSON.parse(out.trim());
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log('\n Adaptive Director — Install\n');
|
|
61
|
+
console.log(' Discovering hosts...\n');
|
|
62
|
+
|
|
63
|
+
const discovery = runDiscover();
|
|
64
|
+
if (!discovery) {
|
|
65
|
+
console.error(' Error: discovery failed.');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const hostsWithSkillDir = [];
|
|
70
|
+
for (const [id, info] of Object.entries(discovery.agents ?? {})) {
|
|
71
|
+
if (info.installed && info.skillPath) {
|
|
72
|
+
hostsWithSkillDir.push({ id, path: info.skillPath });
|
|
73
|
+
} else if (info.installed) {
|
|
74
|
+
console.log(` ! ${id}: installed but skill directory could not be resolved. Skipping.`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (hostsWithSkillDir.length === 0) {
|
|
79
|
+
console.log(' No known host skill directories found. Nothing to install.');
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
console.log(' Installing into detected hosts:');
|
|
84
|
+
for (const h of hostsWithSkillDir) {
|
|
85
|
+
console.log(` [→] ${h.id} — ${h.path}`);
|
|
86
|
+
}
|
|
87
|
+
console.log('');
|
|
88
|
+
|
|
89
|
+
for (const h of hostsWithSkillDir) {
|
|
90
|
+
try {
|
|
91
|
+
installInto(h.path);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
console.error(` ✗ Failed to install for ${h.id}: ${e.message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log('\n Done. Run "adaptive-director doctor" to verify.\n');
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFileSync } from 'node:child_process';
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { join, dirname } from 'node:path';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
function run(script, args = []) {
|
|
11
|
+
try {
|
|
12
|
+
const out = execFileSync(process.execPath, [script, ...args], {
|
|
13
|
+
encoding: 'utf8', timeout: 15000,
|
|
14
|
+
cwd: process.cwd(),
|
|
15
|
+
});
|
|
16
|
+
return JSON.parse(out.trim());
|
|
17
|
+
} catch (e) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const configDir = join(homedir(), '.adaptive-director');
|
|
23
|
+
const configPath = join(configDir, 'config.json');
|
|
24
|
+
|
|
25
|
+
console.log('Refreshing Adaptive Director config...\n');
|
|
26
|
+
|
|
27
|
+
const discovery = run(join(__dirname, 'discover.mjs'));
|
|
28
|
+
if (!discovery) {
|
|
29
|
+
console.error('✗ Discovery failed.');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let existingConfig = {};
|
|
34
|
+
if (existsSync(configPath)) {
|
|
35
|
+
try {
|
|
36
|
+
existingConfig = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
37
|
+
} catch {
|
|
38
|
+
console.warn('! Existing config is invalid, creating a new one.');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const config = {
|
|
43
|
+
version: 1,
|
|
44
|
+
defaultBudget: existingConfig.defaultBudget || 'balanced',
|
|
45
|
+
allowMax: existingConfig.allowMax || false,
|
|
46
|
+
delegateEnabled: existingConfig.delegateEnabled || false,
|
|
47
|
+
hosts: {},
|
|
48
|
+
overrides: existingConfig.overrides || {}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
for (const [id, info] of Object.entries(discovery.agents ?? {})) {
|
|
52
|
+
if (info.installed) {
|
|
53
|
+
config.hosts[id] = {
|
|
54
|
+
enabled: existingConfig.hosts?.[id]?.enabled ?? true,
|
|
55
|
+
skillPath: info.skillPath
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
61
|
+
|
|
62
|
+
console.log(`✓ Config updated successfully.`);
|