expxagents 0.21.0 → 0.21.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.
- package/dist/cli/src/commands/create.js +2 -1
- package/dist/cli/src/commands/doctor.js +6 -4
- package/dist/cli/src/commands/init.js +11 -2
- package/dist/cli/src/commands/install.js +4 -2
- package/dist/cli/src/commands/list.js +5 -3
- package/dist/cli/src/commands/mcp.js +2 -1
- package/dist/cli/src/commands/onboarding.js +4 -2
- package/dist/cli/src/commands/outdated.js +2 -1
- package/dist/cli/src/commands/publish.js +2 -1
- package/dist/cli/src/commands/reorganize.js +2 -1
- package/dist/cli/src/commands/run.js +4 -2
- package/dist/cli/src/commands/sync-templates.js +2 -1
- package/dist/cli/src/commands/whoami.js +3 -2
- package/dist/cli/src/index.js +1 -12
- package/dist/cli/src/mcp/validate.js +2 -1
- package/dist/cli/src/utils/__tests__/command-prefix.test.d.ts +1 -0
- package/dist/cli/src/utils/__tests__/command-prefix.test.js +35 -0
- package/dist/cli/src/utils/__tests__/global-install.test.d.ts +1 -0
- package/dist/cli/src/utils/__tests__/global-install.test.js +25 -0
- package/dist/cli/src/utils/command-prefix.d.ts +5 -0
- package/dist/cli/src/utils/command-prefix.js +15 -0
- package/dist/cli/src/utils/ensure-server.js +55 -5
- package/dist/cli/src/utils/global-install.d.ts +6 -0
- package/dist/cli/src/utils/global-install.js +15 -0
- package/dist/cli/src/utils/version.d.ts +1 -0
- package/dist/cli/src/utils/version.js +12 -0
- package/node_modules/expxagents-knowledge/dist/config.d.ts +4 -0
- package/node_modules/expxagents-knowledge/dist/config.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/config.js +23 -0
- package/node_modules/expxagents-knowledge/dist/config.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/db/connection.d.ts +6 -0
- package/node_modules/expxagents-knowledge/dist/db/connection.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/db/connection.js +69 -0
- package/node_modules/expxagents-knowledge/dist/db/connection.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/db/migrations.d.ts +3 -0
- package/node_modules/expxagents-knowledge/dist/db/migrations.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/db/migrations.js +46 -0
- package/node_modules/expxagents-knowledge/dist/db/migrations.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/db/schema.d.ts +3 -0
- package/node_modules/expxagents-knowledge/dist/db/schema.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/db/schema.js +79 -0
- package/node_modules/expxagents-knowledge/dist/db/schema.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/index.d.ts +15 -0
- package/node_modules/expxagents-knowledge/dist/index.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/index.js +15 -0
- package/node_modules/expxagents-knowledge/dist/index.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/chunker.d.ts +8 -0
- package/node_modules/expxagents-knowledge/dist/ingest/chunker.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/chunker.js +139 -0
- package/node_modules/expxagents-knowledge/dist/ingest/chunker.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/document-loader.d.ts +4 -0
- package/node_modules/expxagents-knowledge/dist/ingest/document-loader.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/document-loader.js +39 -0
- package/node_modules/expxagents-knowledge/dist/ingest/document-loader.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/embedder.d.ts +4 -0
- package/node_modules/expxagents-knowledge/dist/ingest/embedder.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/embedder.js +25 -0
- package/node_modules/expxagents-knowledge/dist/ingest/embedder.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/entity-extractor.d.ts +21 -0
- package/node_modules/expxagents-knowledge/dist/ingest/entity-extractor.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/entity-extractor.js +54 -0
- package/node_modules/expxagents-knowledge/dist/ingest/entity-extractor.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/extraction-queue.d.ts +16 -0
- package/node_modules/expxagents-knowledge/dist/ingest/extraction-queue.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/extraction-queue.js +49 -0
- package/node_modules/expxagents-knowledge/dist/ingest/extraction-queue.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/pipeline.d.ts +27 -0
- package/node_modules/expxagents-knowledge/dist/ingest/pipeline.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/ingest/pipeline.js +83 -0
- package/node_modules/expxagents-knowledge/dist/ingest/pipeline.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/query/graph-traversal.d.ts +41 -0
- package/node_modules/expxagents-knowledge/dist/query/graph-traversal.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/query/graph-traversal.js +62 -0
- package/node_modules/expxagents-knowledge/dist/query/graph-traversal.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/query/knowledge-query.d.ts +31 -0
- package/node_modules/expxagents-knowledge/dist/query/knowledge-query.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/query/knowledge-query.js +106 -0
- package/node_modules/expxagents-knowledge/dist/query/knowledge-query.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/query/vector-search.d.ts +26 -0
- package/node_modules/expxagents-knowledge/dist/query/vector-search.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/query/vector-search.js +57 -0
- package/node_modules/expxagents-knowledge/dist/query/vector-search.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/sources/agent-output.d.ts +10 -0
- package/node_modules/expxagents-knowledge/dist/sources/agent-output.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/sources/agent-output.js +29 -0
- package/node_modules/expxagents-knowledge/dist/sources/agent-output.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/sources/watcher.d.ts +6 -0
- package/node_modules/expxagents-knowledge/dist/sources/watcher.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/sources/watcher.js +42 -0
- package/node_modules/expxagents-knowledge/dist/sources/watcher.js.map +1 -0
- package/node_modules/expxagents-knowledge/dist/types.d.ts +123 -0
- package/node_modules/expxagents-knowledge/dist/types.d.ts.map +1 -0
- package/node_modules/expxagents-knowledge/dist/types.js +2 -0
- package/node_modules/expxagents-knowledge/dist/types.js.map +1 -0
- package/node_modules/expxagents-knowledge/package.json +7 -0
- package/package.json +8 -2
|
@@ -2,6 +2,7 @@ import { spawn } from 'child_process';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import { getCoreAsset } from '../utils/config.js';
|
|
5
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
5
6
|
export async function createCommand(description) {
|
|
6
7
|
const cwd = process.cwd();
|
|
7
8
|
const architectPath = getCoreAsset('solution-architect.agent.md');
|
|
@@ -46,7 +47,7 @@ export async function createCommand(description) {
|
|
|
46
47
|
});
|
|
47
48
|
child.on('exit', (code) => {
|
|
48
49
|
if (code === 0) {
|
|
49
|
-
console.log(
|
|
50
|
+
console.log(`\nSquad created! Run \`${getCommandPrefix()} list\` to see it.`);
|
|
50
51
|
}
|
|
51
52
|
else {
|
|
52
53
|
console.error(`\nArchitect exited with code ${code}`);
|
|
@@ -2,8 +2,10 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
4
|
import { getAssetsDir } from '../utils/config.js';
|
|
5
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
5
6
|
export async function doctorCommand() {
|
|
6
7
|
const cwd = process.cwd();
|
|
8
|
+
const cmd = getCommandPrefix();
|
|
7
9
|
const checks = [];
|
|
8
10
|
// Node.js version
|
|
9
11
|
const nodeVersion = process.version;
|
|
@@ -44,7 +46,7 @@ export async function doctorCommand() {
|
|
|
44
46
|
checks.push({
|
|
45
47
|
name: 'MCP integrations',
|
|
46
48
|
status: 'warn',
|
|
47
|
-
message:
|
|
49
|
+
message: `No MCPs configured. Run: ${cmd} mcp setup <id>`,
|
|
48
50
|
});
|
|
49
51
|
}
|
|
50
52
|
// Project structure
|
|
@@ -54,7 +56,7 @@ export async function doctorCommand() {
|
|
|
54
56
|
checks.push({
|
|
55
57
|
name: `Directory: ${dir}`,
|
|
56
58
|
status: exists ? 'ok' : 'warn',
|
|
57
|
-
message: exists ? 'exists' :
|
|
59
|
+
message: exists ? 'exists' : `missing — run \`${cmd} init\``,
|
|
58
60
|
});
|
|
59
61
|
}
|
|
60
62
|
// .env file
|
|
@@ -62,7 +64,7 @@ export async function doctorCommand() {
|
|
|
62
64
|
checks.push({
|
|
63
65
|
name: '.env file',
|
|
64
66
|
status: envExists ? 'ok' : 'warn',
|
|
65
|
-
message: envExists ? 'exists' :
|
|
67
|
+
message: envExists ? 'exists' : `missing — run \`${cmd} init\``,
|
|
66
68
|
});
|
|
67
69
|
// Company profile
|
|
68
70
|
const companyPath = path.join(cwd, '_expxagents', '_memory', 'company.md');
|
|
@@ -72,7 +74,7 @@ export async function doctorCommand() {
|
|
|
72
74
|
checks.push({
|
|
73
75
|
name: 'Company profile',
|
|
74
76
|
status: configured ? 'ok' : 'warn',
|
|
75
|
-
message: configured ? 'configured' :
|
|
77
|
+
message: configured ? 'configured' : `not configured — run \`${cmd} onboarding\``,
|
|
76
78
|
});
|
|
77
79
|
}
|
|
78
80
|
// Squads count
|
|
@@ -3,6 +3,8 @@ import path from 'path';
|
|
|
3
3
|
import crypto from 'crypto';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
5
|
import { getTemplateDir, getAssetsDir } from '../utils/config.js';
|
|
6
|
+
import { tryGlobalInstall } from '../utils/global-install.js';
|
|
7
|
+
import { getVersion } from '../utils/version.js';
|
|
6
8
|
function getDefaultTemplate(file) {
|
|
7
9
|
if (file === 'company.md') {
|
|
8
10
|
return `<!-- NOT CONFIGURED -->
|
|
@@ -408,6 +410,13 @@ BRIDGE_TIMEOUT_MS=300000
|
|
|
408
410
|
fs.writeFileSync(gitignorePath, gitignoreEntries.join('\n') + '\n', 'utf-8');
|
|
409
411
|
console.log(' Created .gitignore');
|
|
410
412
|
}
|
|
413
|
+
// Try global install
|
|
414
|
+
const version = getVersion();
|
|
415
|
+
const globalInstalled = tryGlobalInstall(version);
|
|
416
|
+
const prefix = globalInstalled ? 'expxagents' : 'npx expxagents';
|
|
417
|
+
if (globalInstalled) {
|
|
418
|
+
console.log('\n ✓ CLI installed globally');
|
|
419
|
+
}
|
|
411
420
|
// MCP Setup
|
|
412
421
|
const mcpsDir = path.resolve('mcps');
|
|
413
422
|
if (fs.existsSync(mcpsDir)) {
|
|
@@ -438,7 +447,7 @@ BRIDGE_TIMEOUT_MS=300000
|
|
|
438
447
|
}
|
|
439
448
|
}
|
|
440
449
|
}
|
|
441
|
-
console.log(
|
|
450
|
+
console.log(`\n Run: ${prefix} mcp setup <id> to configure additional MCPs\n`);
|
|
442
451
|
}
|
|
443
452
|
// Install Python dependencies
|
|
444
453
|
const pythonDeps = ['aiohttp', 'aiofiles', 'python-dotenv'];
|
|
@@ -461,7 +470,7 @@ BRIDGE_TIMEOUT_MS=300000
|
|
|
461
470
|
console.log('\nUpdate complete! Assets refreshed to latest version.');
|
|
462
471
|
}
|
|
463
472
|
else {
|
|
464
|
-
console.log(
|
|
473
|
+
console.log(`\nProject initialized! Run \`${prefix} onboarding\` to configure your profile.`);
|
|
465
474
|
console.log('Use /expxagents in Claude Code to get started.');
|
|
466
475
|
}
|
|
467
476
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
3
4
|
const SKILL_CATALOG = {
|
|
4
5
|
'web-search': {
|
|
5
6
|
description: 'Web search capability (built-in)',
|
|
@@ -34,6 +35,7 @@ const SKILL_CATALOG = {
|
|
|
34
35
|
};
|
|
35
36
|
export async function installCommand(skillName) {
|
|
36
37
|
const cwd = process.cwd();
|
|
38
|
+
const cmd = getCommandPrefix();
|
|
37
39
|
const skillsDir = path.join(cwd, 'skills');
|
|
38
40
|
if (!skillName) {
|
|
39
41
|
console.log('\n Available skills:\n');
|
|
@@ -41,13 +43,13 @@ export async function installCommand(skillName) {
|
|
|
41
43
|
const installed = fs.existsSync(path.join(skillsDir, name));
|
|
42
44
|
console.log(` ${installed ? '[installed]' : ' '} ${name} — ${info.description}`);
|
|
43
45
|
}
|
|
44
|
-
console.log(
|
|
46
|
+
console.log(`\n Usage: ${cmd} install <skill-name>\n`);
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
47
49
|
const skill = SKILL_CATALOG[skillName];
|
|
48
50
|
if (!skill) {
|
|
49
51
|
console.error(` Skill "${skillName}" not found in catalog.`);
|
|
50
|
-
console.log(
|
|
52
|
+
console.log(` Run \`${cmd} install\` to see available skills.`);
|
|
51
53
|
process.exit(1);
|
|
52
54
|
}
|
|
53
55
|
const skillDir = path.join(skillsDir, skillName);
|
|
@@ -3,6 +3,7 @@ import path from 'path';
|
|
|
3
3
|
import yaml from 'js-yaml';
|
|
4
4
|
import { loadSkills } from '../../../core/skills-loader.js';
|
|
5
5
|
import { readState } from '../../../core/state-manager.js';
|
|
6
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
6
7
|
function walkSquads(squadsDir) {
|
|
7
8
|
if (!fs.existsSync(squadsDir))
|
|
8
9
|
return [];
|
|
@@ -70,6 +71,7 @@ function capitalize(s) {
|
|
|
70
71
|
}
|
|
71
72
|
export async function listCommand() {
|
|
72
73
|
const cwd = process.cwd();
|
|
74
|
+
const cmd = getCommandPrefix();
|
|
73
75
|
const squadsDir = path.join(cwd, 'squads');
|
|
74
76
|
const skillsDir = path.join(cwd, 'skills');
|
|
75
77
|
console.log('Squads:');
|
|
@@ -77,7 +79,7 @@ export async function listCommand() {
|
|
|
77
79
|
if (fs.existsSync(squadsDir)) {
|
|
78
80
|
const allSquads = walkSquads(squadsDir);
|
|
79
81
|
if (allSquads.length === 0) {
|
|
80
|
-
console.log(
|
|
82
|
+
console.log(` No squads found. Run \`${cmd} create\` to create one.\n`);
|
|
81
83
|
}
|
|
82
84
|
else {
|
|
83
85
|
const hierarchical = allSquads
|
|
@@ -113,14 +115,14 @@ export async function listCommand() {
|
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
else {
|
|
116
|
-
console.log(
|
|
118
|
+
console.log(` No squads directory. Run \`${cmd} init\` first.\n`);
|
|
117
119
|
}
|
|
118
120
|
// List skills (unchanged)
|
|
119
121
|
console.log('Skills:');
|
|
120
122
|
console.log('-------');
|
|
121
123
|
const skills = loadSkills(skillsDir);
|
|
122
124
|
if (skills.length === 0) {
|
|
123
|
-
console.log(
|
|
125
|
+
console.log(` No skills installed. Run \`${cmd} install <skill>\` to add one.`);
|
|
124
126
|
}
|
|
125
127
|
else {
|
|
126
128
|
for (const skill of skills) {
|
|
@@ -7,6 +7,7 @@ import { detectMcp, detectExtension, resolvePlatformBinary } from '../mcp/detect
|
|
|
7
7
|
import { writeMcpConfig, removeMcpConfig } from '../mcp/setup.js';
|
|
8
8
|
import { getConfiguredMcpIds } from '../mcp/validate.js';
|
|
9
9
|
import { getAssetsDir } from '../utils/config.js';
|
|
10
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
10
11
|
function getMcpsDir() {
|
|
11
12
|
const local = path.resolve('mcps');
|
|
12
13
|
if (fs.existsSync(local))
|
|
@@ -54,7 +55,7 @@ export function mcpCommand() {
|
|
|
54
55
|
}
|
|
55
56
|
console.log('');
|
|
56
57
|
}
|
|
57
|
-
console.log(
|
|
58
|
+
console.log(`Run: ${getCommandPrefix()} mcp setup <id> to configure\n`);
|
|
58
59
|
});
|
|
59
60
|
mcp
|
|
60
61
|
.command('setup <ids...>')
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import readline from 'readline';
|
|
4
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
4
5
|
function ask(rl, question) {
|
|
5
6
|
return new Promise(resolve => rl.question(question, resolve));
|
|
6
7
|
}
|
|
@@ -8,8 +9,9 @@ export async function onboardingCommand() {
|
|
|
8
9
|
const cwd = process.cwd();
|
|
9
10
|
const companyPath = path.join(cwd, '_expxagents', '_memory', 'company.md');
|
|
10
11
|
const prefsPath = path.join(cwd, '_expxagents', '_memory', 'preferences.md');
|
|
12
|
+
const cmd = getCommandPrefix();
|
|
11
13
|
if (!fs.existsSync(path.dirname(companyPath))) {
|
|
12
|
-
console.error(
|
|
14
|
+
console.error(`Project not initialized. Run \`${cmd} init\` first.`);
|
|
13
15
|
process.exit(1);
|
|
14
16
|
}
|
|
15
17
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -31,7 +33,7 @@ export async function onboardingCommand() {
|
|
|
31
33
|
const companyContent = `# Company Profile\n\n## Company\n- **Name:** ${companyName}\n- **Website:** ${companyUrl}\n- **Sector:** ${sector}\n- **Description:** ${description}\n\n## Target Audience\n- **Primary:** ${audience}\n\n## Tone of Voice\n- **Style:** ${toneStyle}\n`;
|
|
32
34
|
fs.writeFileSync(companyPath, companyContent, 'utf-8');
|
|
33
35
|
console.log('\n Profile saved! You can edit it anytime at _expxagents/_memory/company.md');
|
|
34
|
-
console.log(
|
|
36
|
+
console.log(` Run \`${cmd} create\` to design your first squad.\n`);
|
|
35
37
|
}
|
|
36
38
|
finally {
|
|
37
39
|
rl.close();
|
|
@@ -3,6 +3,7 @@ import { resolve, join } from 'node:path';
|
|
|
3
3
|
import { readdirSync, readFileSync, existsSync } from 'node:fs';
|
|
4
4
|
import { RegistryClient, readCredentials } from '@expxagents/registry-client';
|
|
5
5
|
import { load as loadYaml } from 'js-yaml';
|
|
6
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
6
7
|
export function scanInstalledSquads(squadsDir) {
|
|
7
8
|
const installed = [];
|
|
8
9
|
if (!existsSync(squadsDir))
|
|
@@ -83,5 +84,5 @@ export const outdatedCommand = new Command('outdated')
|
|
|
83
84
|
for (const o of outdated) {
|
|
84
85
|
console.log(` ${o.fullName} ${o.current} \u2192 ${o.latest}`);
|
|
85
86
|
}
|
|
86
|
-
console.log(`\nRun
|
|
87
|
+
console.log(`\nRun \`${getCommandPrefix()} update\` to update all.`);
|
|
87
88
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { RegistryClient, readCredentials } from '@expxagents/registry-client';
|
|
4
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
4
5
|
export const publishCommand = new Command('publish')
|
|
5
6
|
.description('Publish a squad to the registry')
|
|
6
7
|
.argument('[dir]', 'Squad directory', '.')
|
|
@@ -8,7 +9,7 @@ export const publishCommand = new Command('publish')
|
|
|
8
9
|
.action(async (dir, options) => {
|
|
9
10
|
const creds = readCredentials();
|
|
10
11
|
if (!creds) {
|
|
11
|
-
console.error(
|
|
12
|
+
console.error(`Not logged in. Run: ${getCommandPrefix()} login`);
|
|
12
13
|
process.exit(1);
|
|
13
14
|
}
|
|
14
15
|
const squadDir = resolve(dir);
|
|
@@ -2,6 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import * as readline from 'readline';
|
|
4
4
|
import yaml from 'js-yaml';
|
|
5
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
5
6
|
// Walk squadsDir recursively, return all squad summaries
|
|
6
7
|
function discoverAllSquads(squadsDir) {
|
|
7
8
|
const result = [];
|
|
@@ -214,7 +215,7 @@ export async function reorganizeCommand() {
|
|
|
214
215
|
const cwd = process.cwd();
|
|
215
216
|
const squadsDir = path.join(cwd, 'squads');
|
|
216
217
|
if (!fs.existsSync(squadsDir)) {
|
|
217
|
-
console.error(
|
|
218
|
+
console.error(`No squads directory found. Run \`${getCommandPrefix()} init\` first.`);
|
|
218
219
|
process.exit(1);
|
|
219
220
|
}
|
|
220
221
|
console.log('Escaneando squads...\n');
|
|
@@ -5,6 +5,7 @@ import { loadSquad, findSquadDir } from '../../../core/squad-loader.js';
|
|
|
5
5
|
import { createInitialState, readState, writeState, updateAgentStatus, updateStep, setHandoff, setSquadStatus, HANDOFF_DELAY_MS, } from '../../../core/state-manager.js';
|
|
6
6
|
import { loadSkills } from '../../../core/skills-loader.js';
|
|
7
7
|
import { getCoreAsset } from '../utils/config.js';
|
|
8
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
8
9
|
import { runWithProvider } from '../runners/provider-runner.js';
|
|
9
10
|
import { estimateCost, formatCost } from '../runners/cost-tracker.js';
|
|
10
11
|
function delay(ms) {
|
|
@@ -135,8 +136,9 @@ export async function runCommand(name) {
|
|
|
135
136
|
const squadsDir = path.join(cwd, 'squads');
|
|
136
137
|
const squadDir = findSquadDir(squadsDir, name);
|
|
137
138
|
const skillsDir = path.join(cwd, 'skills');
|
|
139
|
+
const cmd = getCommandPrefix();
|
|
138
140
|
if (!squadDir) {
|
|
139
|
-
console.error(`Squad "${name}" not found. Run
|
|
141
|
+
console.error(`Squad "${name}" not found. Run \`${cmd} list\` to see available squads.`);
|
|
140
142
|
process.exit(1);
|
|
141
143
|
}
|
|
142
144
|
let config;
|
|
@@ -155,7 +157,7 @@ export async function runCommand(name) {
|
|
|
155
157
|
}
|
|
156
158
|
const existingState = readState(squadDir);
|
|
157
159
|
if (existingState && existingState.status === 'running') {
|
|
158
|
-
console.error(`Squad "${name}" is already running. Use
|
|
160
|
+
console.error(`Squad "${name}" is already running. Use \`${cmd} stop ${name}\` first.`);
|
|
159
161
|
process.exit(1);
|
|
160
162
|
}
|
|
161
163
|
const outputDir = getNextVersionDir(squadDir);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { findSquadDir, loadSquad } from '../../../core/squad-loader.js';
|
|
4
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
4
5
|
/**
|
|
5
6
|
* Find all .pen files in a squad's templates/ directory.
|
|
6
7
|
*/
|
|
@@ -65,7 +66,7 @@ export async function syncTemplatesCommand(squadFilter) {
|
|
|
65
66
|
const cwd = process.cwd();
|
|
66
67
|
const squadsDir = path.join(cwd, 'squads');
|
|
67
68
|
if (!fs.existsSync(squadsDir)) {
|
|
68
|
-
console.error(
|
|
69
|
+
console.error(`No squads/ directory found. Run \`${getCommandPrefix()} init\` first.`);
|
|
69
70
|
process.exit(1);
|
|
70
71
|
}
|
|
71
72
|
let squadDirs;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { RegistryClient, readCredentials } from '@expxagents/registry-client';
|
|
3
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
3
4
|
export const whoamiCommand = new Command('whoami')
|
|
4
5
|
.description('Show current registry identity')
|
|
5
6
|
.action(async () => {
|
|
6
7
|
const creds = readCredentials();
|
|
7
8
|
if (!creds) {
|
|
8
|
-
console.error(
|
|
9
|
+
console.error(`Not logged in. Run: ${getCommandPrefix()} login`);
|
|
9
10
|
process.exit(1);
|
|
10
11
|
}
|
|
11
12
|
const client = new RegistryClient({ registryUrl: creds.registryUrl, apiKey: creds.apiKey });
|
|
@@ -17,7 +18,7 @@ export const whoamiCommand = new Command('whoami')
|
|
|
17
18
|
console.log(` Registry: ${creds.registryUrl}`);
|
|
18
19
|
}
|
|
19
20
|
catch {
|
|
20
|
-
console.error(
|
|
21
|
+
console.error(`\u2717 Invalid credentials. Run: ${getCommandPrefix()} login`);
|
|
21
22
|
process.exit(1);
|
|
22
23
|
}
|
|
23
24
|
});
|
package/dist/cli/src/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
1
|
import { Command } from 'commander';
|
|
3
2
|
import { initCommand } from './commands/init.js';
|
|
4
3
|
import { createCommand } from './commands/create.js';
|
|
@@ -27,17 +26,7 @@ import { searchCommand } from './commands/search.js';
|
|
|
27
26
|
import { infoCommand } from './commands/info.js';
|
|
28
27
|
import { outdatedCommand } from './commands/outdated.js';
|
|
29
28
|
import { updateCommand } from './commands/update.js';
|
|
30
|
-
import {
|
|
31
|
-
function getVersion() {
|
|
32
|
-
try {
|
|
33
|
-
const pkgPath = `${findPackageRoot()}/package.json`;
|
|
34
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
35
|
-
return pkg.version ?? '0.0.0';
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return '0.0.0';
|
|
39
|
-
}
|
|
40
|
-
}
|
|
29
|
+
import { getVersion } from './utils/version.js';
|
|
41
30
|
const program = new Command();
|
|
42
31
|
program
|
|
43
32
|
.name('expxagents')
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { getCommandPrefix } from '../utils/command-prefix.js';
|
|
3
4
|
export function getConfiguredMcpIds(projectDir) {
|
|
4
5
|
const mcpPath = path.join(projectDir, '.mcp.json');
|
|
5
6
|
if (!fs.existsSync(mcpPath))
|
|
@@ -18,6 +19,6 @@ export function validateSquadMcps(squadMcps, configuredMcps) {
|
|
|
18
19
|
const missing = squadMcps.filter(m => !configuredMcps.includes(m));
|
|
19
20
|
if (missing.length > 0) {
|
|
20
21
|
throw new Error(`Squad requires MCPs not configured: ${missing.join(', ')}.\n` +
|
|
21
|
-
`Run:
|
|
22
|
+
`Run: ${getCommandPrefix()} mcp setup ${missing.join(' ')}`);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach } from 'vitest';
|
|
2
|
+
import { getCommandPrefix } from '../command-prefix.js';
|
|
3
|
+
describe('getCommandPrefix', () => {
|
|
4
|
+
const originalArgv = process.argv;
|
|
5
|
+
const originalEnv = { ...process.env };
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
process.argv = originalArgv;
|
|
8
|
+
process.env = originalEnv;
|
|
9
|
+
});
|
|
10
|
+
it('returns "npx expxagents" when npm_execpath contains npx', () => {
|
|
11
|
+
process.env.npm_execpath = '/usr/local/lib/node_modules/npm/bin/npx-cli.js';
|
|
12
|
+
process.argv = [process.argv[0], '/usr/local/bin/expxagents'];
|
|
13
|
+
expect(getCommandPrefix()).toBe('npx expxagents');
|
|
14
|
+
});
|
|
15
|
+
it('returns "npx expxagents" when argv[1] contains _npx (fallback)', () => {
|
|
16
|
+
delete process.env.npm_execpath;
|
|
17
|
+
process.argv = [process.argv[0], '/home/user/.npm/_npx/abc123/bin/expxagents.js'];
|
|
18
|
+
expect(getCommandPrefix()).toBe('npx expxagents');
|
|
19
|
+
});
|
|
20
|
+
it('returns "expxagents" for global install on Unix', () => {
|
|
21
|
+
delete process.env.npm_execpath;
|
|
22
|
+
process.argv = [process.argv[0], '/usr/local/bin/expxagents'];
|
|
23
|
+
expect(getCommandPrefix()).toBe('expxagents');
|
|
24
|
+
});
|
|
25
|
+
it('returns "expxagents" for global install on Windows', () => {
|
|
26
|
+
delete process.env.npm_execpath;
|
|
27
|
+
process.argv = [process.argv[0], 'C:\\Users\\X\\AppData\\Roaming\\npm\\expxagents'];
|
|
28
|
+
expect(getCommandPrefix()).toBe('expxagents');
|
|
29
|
+
});
|
|
30
|
+
it('returns "expxagents" when both env and argv are empty', () => {
|
|
31
|
+
delete process.env.npm_execpath;
|
|
32
|
+
process.argv = [process.argv[0], ''];
|
|
33
|
+
expect(getCommandPrefix()).toBe('expxagents');
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { tryGlobalInstall } from '../global-install.js';
|
|
4
|
+
vi.mock('child_process', () => ({
|
|
5
|
+
execSync: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
const mockExecSync = vi.mocked(execSync);
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
vi.restoreAllMocks();
|
|
10
|
+
});
|
|
11
|
+
describe('tryGlobalInstall', () => {
|
|
12
|
+
it('returns true when npm install -g succeeds', () => {
|
|
13
|
+
mockExecSync.mockReturnValue(Buffer.from(''));
|
|
14
|
+
expect(tryGlobalInstall('0.20.1')).toBe(true);
|
|
15
|
+
expect(mockExecSync).toHaveBeenCalledWith('npm install -g expxagents@0.20.1', { stdio: 'pipe', timeout: 60000 });
|
|
16
|
+
});
|
|
17
|
+
it('returns false when npm install -g fails', () => {
|
|
18
|
+
mockExecSync.mockImplementation(() => { throw new Error('EACCES'); });
|
|
19
|
+
expect(tryGlobalInstall('0.20.1')).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
it('never throws', () => {
|
|
22
|
+
mockExecSync.mockImplementation(() => { throw new Error('network error'); });
|
|
23
|
+
expect(() => tryGlobalInstall('1.0.0')).not.toThrow();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects whether the CLI is running globally or via npx.
|
|
3
|
+
* Returns 'expxagents' for global, 'npx expxagents' for npx.
|
|
4
|
+
*/
|
|
5
|
+
export function getCommandPrefix() {
|
|
6
|
+
const npmExecPath = process.env.npm_execpath ?? '';
|
|
7
|
+
if (npmExecPath.includes('npx')) {
|
|
8
|
+
return 'npx expxagents';
|
|
9
|
+
}
|
|
10
|
+
const execPath = process.argv[1] ?? '';
|
|
11
|
+
if (execPath.includes('_npx')) {
|
|
12
|
+
return 'npx expxagents';
|
|
13
|
+
}
|
|
14
|
+
return 'expxagents';
|
|
15
|
+
}
|
|
@@ -1,7 +1,53 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
1
|
+
import { execSync, spawn } from 'child_process';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { resolveServerPaths } from './server-paths.js';
|
|
5
|
+
const MAX_HEALTH_CHECK_ATTEMPTS = 30;
|
|
6
|
+
const HEALTH_CHECK_INTERVAL_MS = 500;
|
|
7
|
+
/**
|
|
8
|
+
* Kill the process listening on the given port (cross-platform).
|
|
9
|
+
*/
|
|
10
|
+
function killProcessOnPort(port) {
|
|
11
|
+
if (process.platform === 'win32') {
|
|
12
|
+
// Find PID using netstat, then kill it
|
|
13
|
+
try {
|
|
14
|
+
const output = execSync(`netstat -ano | findstr :${port} | findstr LISTENING`, {
|
|
15
|
+
encoding: 'utf-8',
|
|
16
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
17
|
+
});
|
|
18
|
+
const pids = new Set(output
|
|
19
|
+
.split('\n')
|
|
20
|
+
.map((line) => line.trim().split(/\s+/).pop())
|
|
21
|
+
.filter((pid) => !!pid && pid !== '0'));
|
|
22
|
+
for (const pid of pids) {
|
|
23
|
+
execSync(`taskkill /PID ${pid} /F`, { stdio: 'ignore' });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new Error(`Could not stop existing server on port ${port}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
execSync(`lsof -ti:${port} | xargs kill -9`, { stdio: 'ignore' });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Poll the health endpoint until the server responds OK or max attempts reached.
|
|
36
|
+
*/
|
|
37
|
+
async function waitForHealthy(port) {
|
|
38
|
+
for (let i = 0; i < MAX_HEALTH_CHECK_ATTEMPTS; i++) {
|
|
39
|
+
try {
|
|
40
|
+
const res = await fetch(`http://localhost:${port}/api/health`);
|
|
41
|
+
if (res.ok)
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Server not ready yet
|
|
46
|
+
}
|
|
47
|
+
await new Promise((resolve) => setTimeout(resolve, HEALTH_CHECK_INTERVAL_MS));
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
5
51
|
/**
|
|
6
52
|
* Ensure the production server is running on the given port.
|
|
7
53
|
* If a dev server is detected (health OK but no dashboard), it is killed and replaced.
|
|
@@ -32,8 +78,7 @@ export async function ensureProductionServer(port) {
|
|
|
32
78
|
// Server is running but not serving dashboard (dev mode) — kill it
|
|
33
79
|
console.log('Detected dev server on port ' + port + ', restarting in production mode...');
|
|
34
80
|
try {
|
|
35
|
-
|
|
36
|
-
execSync(`lsof -ti:${port} | xargs kill -9`, { stdio: 'ignore' });
|
|
81
|
+
killProcessOnPort(port);
|
|
37
82
|
// Wait for port to free up
|
|
38
83
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
39
84
|
}
|
|
@@ -71,6 +116,11 @@ export async function ensureProductionServer(port) {
|
|
|
71
116
|
console.error(`Failed to start server: ${err.message}`);
|
|
72
117
|
process.exit(1);
|
|
73
118
|
});
|
|
74
|
-
//
|
|
75
|
-
|
|
119
|
+
// Poll health endpoint until server is ready (up to 15 seconds)
|
|
120
|
+
const healthy = await waitForHealthy(port);
|
|
121
|
+
if (!healthy) {
|
|
122
|
+
console.error(`Server failed to start on port ${port} within ${(MAX_HEALTH_CHECK_ATTEMPTS * HEALTH_CHECK_INTERVAL_MS) / 1000} seconds.`);
|
|
123
|
+
console.error('Check the server logs above for errors.');
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
76
126
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Attempts to install expxagents globally via npm.
|
|
4
|
+
* Returns true if successful, false otherwise.
|
|
5
|
+
* Never throws — failures are silent.
|
|
6
|
+
*/
|
|
7
|
+
export function tryGlobalInstall(version) {
|
|
8
|
+
try {
|
|
9
|
+
execSync(`npm install -g expxagents@${version}`, { stdio: 'pipe', timeout: 60000 });
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getVersion(): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { findPackageRoot } from './config.js';
|
|
3
|
+
export function getVersion() {
|
|
4
|
+
try {
|
|
5
|
+
const pkgPath = `${findPackageRoot()}/package.json`;
|
|
6
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
7
|
+
return pkg.version ?? '0.0.0';
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return '0.0.0';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,cAAc,EAAE,eAQ5B,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,eAAe,CAa1F"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export const DEFAULT_CONFIG = {
|
|
3
|
+
enabled: true,
|
|
4
|
+
db_path: '',
|
|
5
|
+
embedder: { provider: 'auto', batch_size: 32 },
|
|
6
|
+
chunker: { max_tokens: 512, overlap: 0.2 },
|
|
7
|
+
graph: { enabled: true, extract_on_ingest: true, dedup_threshold: 0.85 },
|
|
8
|
+
auto_ingest: { agent_outputs: true, activity_logs: false, watch_paths: [] },
|
|
9
|
+
limits: { max_document_size_mb: 10, max_documents: 10000, max_entities: 50000 },
|
|
10
|
+
};
|
|
11
|
+
export function loadKnowledgeConfig(projectRoot, dataDir) {
|
|
12
|
+
const config = structuredClone(DEFAULT_CONFIG);
|
|
13
|
+
config.db_path = path.join(dataDir ?? path.join(projectRoot, '.expxagents', 'data'), 'knowledge.db');
|
|
14
|
+
// Env var overrides (take precedence over yaml)
|
|
15
|
+
if (process.env.KNOWLEDGE_ENABLED !== undefined) {
|
|
16
|
+
config.enabled = process.env.KNOWLEDGE_ENABLED !== 'false';
|
|
17
|
+
}
|
|
18
|
+
if (process.env.KNOWLEDGE_EMBEDDER_PROVIDER) {
|
|
19
|
+
config.embedder.provider = process.env.KNOWLEDGE_EMBEDDER_PROVIDER;
|
|
20
|
+
}
|
|
21
|
+
return config;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE;IAC9C,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE;IAC1C,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE;IACxE,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;IAC3E,MAAM,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE;CAChF,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,WAAmB,EAAE,OAAgB;IACvE,MAAM,MAAM,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,cAAc,CAAC,CAAC;IAErG,gDAAgD;IAChD,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAChD,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,OAAO,CAAC;IAC7D,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,CAAC;QAC5C,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,2BAAsE,CAAC;IAChH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
export declare function getKnowledgeDb(dbPath: string): Database.Database;
|
|
3
|
+
export declare function isVecLoaded(): boolean;
|
|
4
|
+
export declare function closeKnowledgeDb(): void;
|
|
5
|
+
export declare function createTestDb(): Database.Database;
|
|
6
|
+
//# sourceMappingURL=connection.d.ts.map
|