adaptive-director-skill 1.1.0 → 1.1.2

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.
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync, spawnSync } 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
+ const args = process.argv.slice(2);
11
+ const subcmd = args[0] || 'help';
12
+
13
+ function run(script, scriptArgs = []) {
14
+ try {
15
+ const out = execFileSync(process.execPath, [script, ...scriptArgs], {
16
+ encoding: 'utf8',
17
+ timeout: 15000,
18
+ cwd: process.cwd(),
19
+ env: process.env,
20
+ });
21
+ return JSON.parse(out.trim());
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+
27
+ if (subcmd === 'help' || subcmd === '--help' || subcmd === '-h') {
28
+ console.log(`Adaptive Director — Delegate Skills Management
29
+
30
+ Usage:
31
+ adaptive-director delegate <subcommand> [options]
32
+
33
+ Subcommands:
34
+ install Install delegate-skills via official installer and update config
35
+ status Display delegate-skills discovery, detected relays, and lanes
36
+ help Show this help message
37
+
38
+ Examples:
39
+ adaptive-director delegate install
40
+ adaptive-director delegate status
41
+ `);
42
+ process.exit(0);
43
+ }
44
+
45
+ if (subcmd === 'install') {
46
+ const setupScript = join(__dirname, 'setup.mjs');
47
+ const forwardArgs = [setupScript, '--with-delegate', '--delegate-only', ...args.slice(1)];
48
+ const res = spawnSync(process.execPath, forwardArgs, {
49
+ stdio: 'inherit',
50
+ env: process.env,
51
+ });
52
+ process.exit(res.status ?? 0);
53
+ }
54
+
55
+ if (subcmd === 'status') {
56
+ console.log('\nAdaptive Director — Delegate Integration Status\n');
57
+
58
+ const configPath = join(homedir(), '.adaptive-director', 'config.json');
59
+ let config = {};
60
+ if (existsSync(configPath)) {
61
+ try {
62
+ config = JSON.parse(readFileSync(configPath, 'utf8'));
63
+ } catch {}
64
+ }
65
+
66
+ const discovery = run(join(__dirname, 'discover.mjs'));
67
+ const ds = discovery?.delegateSkills ?? { installed: false, relays: [], lanes: {} };
68
+
69
+ console.log(` Installed: ${ds.installed ? 'Yes' : 'No'}`);
70
+ console.log(` Config execution: ${config.execution || 'native'}`);
71
+ console.log(` Config enabled: ${config.delegate?.enabled ?? config.delegateEnabled ?? false}`);
72
+ if (config.delegate?.lastInstallAttempt) {
73
+ console.log(` Last install attempt: ${config.delegate.lastInstallAttempt}`);
74
+ }
75
+
76
+ const skills = ds.skills ?? ds.relays ?? [];
77
+ const relays = ds.relays ?? [];
78
+ console.log(`\n Detected Delegate Skills (${skills.length}):`);
79
+ if (skills.length > 0) {
80
+ for (const s of skills) {
81
+ const isRelay = relays.includes(s);
82
+ console.log(` - ${s}${isRelay ? ' (execution relay)' : ''}`);
83
+ }
84
+ } else {
85
+ console.log(' (none detected)');
86
+ }
87
+
88
+ const lanes = ds.lanes ?? {};
89
+ const laneKeys = Object.keys(lanes);
90
+ console.log(`\n Active Execution Lanes (${laneKeys.length}):`);
91
+ if (laneKeys.length > 0) {
92
+ for (const k of laneKeys) {
93
+ const lane = lanes[k];
94
+ console.log(` - ${k}: agent=${lane.agent || lane.implementer || 'unknown'}${lane.model ? `, model=${lane.model}` : ''}`);
95
+ }
96
+ } else {
97
+ console.log(' (none configured)');
98
+ }
99
+
100
+ console.log('');
101
+ process.exit(0);
102
+ }
103
+
104
+ console.error(`Unknown delegate subcommand: ${subcmd}`);
105
+ console.log(`Run 'adaptive-director delegate help' for usage.`);
106
+ process.exit(1);
@@ -13,7 +13,7 @@
13
13
  */
14
14
 
15
15
  import { execFileSync, execSync } from 'node:child_process'
16
- import { existsSync, readFileSync } from 'node:fs'
16
+ import { existsSync, readFileSync, readdirSync } from 'node:fs'
17
17
  import { join } from 'node:path'
18
18
  import { homedir } from 'node:os'
19
19
  import { discoverHostModels } from '../skills/adaptive-director/scripts/discover-models.mjs'
@@ -53,16 +53,27 @@ function findBinary(bins) {
53
53
  return null
54
54
  }
55
55
 
56
- function getVersion(bin, args) {
57
- try {
58
- const out = execFileSync(bin, args, {
59
- encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore']
60
- })
61
- return out.trim().split('\n')[0].trim()
62
- } catch {
63
- return null
64
- }
65
- }
56
+ function getVersion(bin, args) {
57
+ try {
58
+ const out = execFileSync(bin, args, {
59
+ encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore']
60
+ })
61
+ return out.trim().split('\n')[0].trim()
62
+ } catch {
63
+ if (process.platform !== 'win32') return null
64
+ try {
65
+ const quotedBin = `"${bin.replace(/"/g, '""')}"`
66
+ const quotedArgs = args.map(a => `"${String(a).replace(/"/g, '""')}"`).join(' ')
67
+ const out = execSync(`${quotedBin} ${quotedArgs}`, {
68
+ encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'],
69
+ windowsHide: true,
70
+ })
71
+ return out.trim().split('\n')[0].trim()
72
+ } catch {
73
+ return null
74
+ }
75
+ }
76
+ }
66
77
 
67
78
  // ─── Delegate-skills fleet ────────────────────────────────────────────────────
68
79
 
@@ -145,16 +156,44 @@ function discoverDelegate() {
145
156
  } catch {}
146
157
  }
147
158
 
148
- const installed = Object.keys(lanes).length > 0 || hasAgentsSkills || hasSkillLock
159
+ // Detect installed delegate relays across candidate directories
160
+ const relayDirs = [
161
+ agentsSkillsDir,
162
+ codexSkillsDir,
163
+ join(process.cwd(), '.agents', 'skills'),
164
+ join(process.cwd(), 'delegate-skills', 'skills'),
165
+ join(homedir(), '.skills', 'amElnagdy', 'delegate-skills', 'skills'),
166
+ ]
167
+ const skillsSet = new Set()
168
+ const relaysSet = new Set()
169
+ for (const dir of relayDirs) {
170
+ if (!existsSync(dir)) continue
171
+ try {
172
+ const entries = readdirSync(dir, { withFileTypes: true })
173
+ for (const entry of entries) {
174
+ if (!entry.isDirectory()) continue
175
+ if (entry.name.endsWith('-delegate') || entry.name === 'delegate-setup' || entry.name.startsWith('delegate-')) {
176
+ skillsSet.add(entry.name)
177
+ if (entry.name.endsWith('-delegate')) {
178
+ relaysSet.add(entry.name)
179
+ }
180
+ }
181
+ }
182
+ } catch {}
183
+ }
184
+ const skills = Array.from(skillsSet).sort()
185
+ const relays = Array.from(relaysSet).sort()
186
+
187
+ const installed = Object.keys(lanes).length > 0 || hasAgentsSkills || hasSkillLock || skills.length > 0
149
188
 
150
189
  // If installed but no explicit fleet lanes file configured, synthesize lanes from installed delegate skills
151
- if (installed && Object.keys(lanes).length === 0 && hasAgentsSkills) {
152
- if (existsSync(join(agentsSkillsDir, 'codex-delegate'))) {
190
+ if (installed && Object.keys(lanes).length === 0 && (hasAgentsSkills || relays.length > 0)) {
191
+ if (relays.includes('codex-delegate') || existsSync(join(agentsSkillsDir, 'codex-delegate'))) {
153
192
  lanes.feature = { agent: 'codex', implementer: 'codex' }
154
193
  lanes.implement = { agent: 'codex', implementer: 'codex' }
155
194
  lanes.fix = { agent: 'codex', implementer: 'codex' }
156
195
  }
157
- if (existsSync(join(agentsSkillsDir, 'agy-delegate'))) {
196
+ if (relays.includes('agy-delegate') || existsSync(join(agentsSkillsDir, 'agy-delegate'))) {
158
197
  lanes.plan = { agent: 'agy', implementer: 'agy' }
159
198
  lanes.review = { agent: 'agy', implementer: 'agy' }
160
199
  lanes.verify = { agent: 'agy', implementer: 'agy' }
@@ -164,7 +203,9 @@ function discoverDelegate() {
164
203
  return {
165
204
  installed,
166
205
  lanes,
167
- source: hasSkillLock ? 'amElnagdy/delegate-skills' : (hasAgentsSkills ? 'local-skills' : (Object.keys(lanes).length > 0 ? 'fleet-config' : null))
206
+ skills,
207
+ relays,
208
+ source: hasSkillLock ? 'amElnagdy/delegate-skills' : (hasAgentsSkills ? 'local-skills' : (Object.keys(lanes).length > 0 ? 'fleet-config' : (skills.length > 0 ? 'detected-skills' : null)))
168
209
  }
169
210
  }
170
211
 
@@ -7,11 +7,12 @@ import { fileURLToPath } from 'node:url';
7
7
 
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
9
 
10
- function run(script, args = []) {
10
+ function run(script, args = [], env = process.env) {
11
11
  try {
12
12
  const out = execFileSync(process.execPath, [script, ...args], {
13
13
  encoding: 'utf8', timeout: 15000,
14
14
  cwd: process.cwd(),
15
+ env,
15
16
  });
16
17
  return JSON.parse(out.trim());
17
18
  } catch {
@@ -65,9 +66,10 @@ if (check('Registry exists', existsSync(registryPath))) {
65
66
  }
66
67
 
67
68
  // ── Config ────────────────────────────────────────────────────────────────
69
+ let configObj = null;
68
70
  if (check('Config exists', existsSync(configPath), 'adaptive-director setup')) {
69
71
  try {
70
- JSON.parse(readFileSync(configPath, 'utf8'));
72
+ configObj = JSON.parse(readFileSync(configPath, 'utf8'));
71
73
  check('Config valid', true);
72
74
  } catch {
73
75
  allGood &= check('Config valid', false, 'rm ~/.adaptive-director/config.json && adaptive-director setup');
@@ -99,7 +101,7 @@ allGood &= check('Resume script exists', existsSync(join(skillRoot, 'scripts'
99
101
 
100
102
  // ── Host discovery ────────────────────────────────────────────────────────
101
103
  console.log('');
102
- const discovery = run(join(__dirname, 'discover.mjs'));
104
+ const discovery = run(join(__dirname, 'discover.mjs'), [], process.env);
103
105
  if (discovery) {
104
106
  let anyHost = false;
105
107
  for (const [id, info] of Object.entries(discovery.agents ?? {})) {
@@ -122,11 +124,18 @@ if (discovery) {
122
124
  if (!anyHost) warn('No supported hosts detected');
123
125
 
124
126
  console.log('');
125
- const ds = discovery.delegateSkills ?? { installed: false };
127
+ const ds = discovery.delegateSkills ?? { installed: false, skills: [], relays: [], lanes: {} };
126
128
  if (ds.installed) {
127
- check(`delegate-skills detected (${Object.keys(ds.lanes ?? {}).length} lane(s))`, true);
129
+ const skillCount = (ds.skills ?? ds.relays ?? []).length;
130
+ const laneCount = Object.keys(ds.lanes ?? {}).length;
131
+ check(`delegate-skills detected (${skillCount} delegate skill(s), ${laneCount} lane(s))`, true);
128
132
  } else {
129
- warn('delegate-skills not detected (optional)');
133
+ warn('delegate-skills not detected (optional — native execution active)');
134
+ if (configObj?.delegate?.lastInstallAttempt === 'failed') {
135
+ warn('Last delegate-skills install attempt failed (run "adaptive-director delegate install" to retry)');
136
+ } else if (configObj?.delegate?.lastInstallAttempt === 'unverified') {
137
+ warn('delegate-skills installation unverified: no relays detected');
138
+ }
130
139
  }
131
140
  } else {
132
141
  allGood &= check('Discovery script works', false, 'Check Node version or reinstall');
@@ -1,97 +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');
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');
@@ -7,11 +7,12 @@ import { fileURLToPath } from 'node:url';
7
7
 
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
9
 
10
- function run(script, args = []) {
10
+ function run(script, args = [], env = process.env) {
11
11
  try {
12
12
  const out = execFileSync(process.execPath, [script, ...args], {
13
13
  encoding: 'utf8', timeout: 15000,
14
14
  cwd: process.cwd(),
15
+ env,
15
16
  });
16
17
  return JSON.parse(out.trim());
17
18
  } catch (e) {
@@ -24,7 +25,7 @@ const configPath = join(configDir, 'config.json');
24
25
 
25
26
  console.log('Refreshing Adaptive Director config...\n');
26
27
 
27
- const discovery = run(join(__dirname, 'discover.mjs'));
28
+ const discovery = run(join(__dirname, 'discover.mjs'), [], process.env);
28
29
  if (!discovery) {
29
30
  console.error('✗ Discovery failed.');
30
31
  process.exit(1);
@@ -39,11 +40,20 @@ if (existsSync(configPath)) {
39
40
  }
40
41
  }
41
42
 
43
+ const delegateInstalled = Boolean(discovery.delegateSkills?.installed);
44
+ const delegateEnabled = existingConfig.delegate?.enabled ?? existingConfig.delegateEnabled ?? false;
45
+
42
46
  const config = {
43
47
  version: 1,
48
+ execution: existingConfig.execution || 'native',
44
49
  defaultBudget: existingConfig.defaultBudget || 'balanced',
45
50
  allowMax: existingConfig.allowMax || false,
46
- delegateEnabled: existingConfig.delegateEnabled || false,
51
+ delegateEnabled,
52
+ delegate: {
53
+ installed: delegateInstalled,
54
+ enabled: delegateEnabled,
55
+ ...(existingConfig.delegate?.lastInstallAttempt ? { lastInstallAttempt: existingConfig.delegate.lastInstallAttempt } : {})
56
+ },
47
57
  hosts: {},
48
58
  overrides: existingConfig.overrides || {}
49
59
  };
@@ -51,6 +61,7 @@ const config = {
51
61
  for (const [id, info] of Object.entries(discovery.agents ?? {})) {
52
62
  if (info.installed) {
53
63
  config.hosts[id] = {
64
+ ...existingConfig.hosts?.[id],
54
65
  enabled: existingConfig.hosts?.[id]?.enabled ?? true,
55
66
  skillPath: info.skillPath
56
67
  };