expxagents 0.10.6 → 0.10.7
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/__tests__/cli.test.d.ts +1 -0
- package/dist/cli/src/__tests__/cli.test.js +23 -0
- package/dist/cli/src/commands/create.d.ts +1 -0
- package/dist/cli/src/commands/create.js +53 -0
- package/dist/cli/src/commands/doctor.d.ts +1 -0
- package/dist/cli/src/commands/doctor.js +86 -0
- package/dist/cli/src/commands/init.d.ts +3 -0
- package/dist/cli/src/commands/init.js +387 -0
- package/dist/cli/src/commands/install.d.ts +1 -0
- package/dist/cli/src/commands/install.js +65 -0
- package/dist/cli/src/commands/jarvis.d.ts +1 -0
- package/dist/cli/src/commands/jarvis.js +63 -0
- package/dist/cli/src/commands/list.d.ts +1 -0
- package/dist/cli/src/commands/list.js +58 -0
- package/dist/cli/src/commands/onboarding.d.ts +1 -0
- package/dist/cli/src/commands/onboarding.js +39 -0
- package/dist/cli/src/commands/run.d.ts +1 -0
- package/dist/cli/src/commands/run.js +226 -0
- package/dist/cli/src/commands/server.d.ts +1 -0
- package/dist/cli/src/commands/server.js +22 -0
- package/dist/cli/src/commands/stop.d.ts +1 -0
- package/dist/cli/src/commands/stop.js +23 -0
- package/dist/cli/src/commands/uninstall.d.ts +1 -0
- package/dist/cli/src/commands/uninstall.js +12 -0
- package/dist/cli/src/commands/virtual-office.d.ts +1 -0
- package/dist/cli/src/commands/virtual-office.js +68 -0
- package/dist/cli/src/index.d.ts +1 -0
- package/dist/cli/src/index.js +68 -0
- package/dist/cli/src/utils/config.d.ts +39 -0
- package/dist/cli/src/utils/config.js +79 -0
- package/dist/cli/src/utils/server-paths.d.ts +9 -0
- package/dist/cli/src/utils/server-paths.js +29 -0
- package/dist/core/skills-loader.d.ts +16 -0
- package/dist/core/skills-loader.js +61 -0
- package/dist/core/squad-loader.d.ts +26 -0
- package/dist/core/squad-loader.js +51 -0
- package/dist/core/state-manager.d.ts +45 -0
- package/dist/core/state-manager.js +90 -0
- package/dist/server/api/activity-routes.d.ts +8 -0
- package/dist/server/api/activity-routes.d.ts.map +1 -0
- package/dist/server/api/activity-routes.js +34 -0
- package/dist/server/api/activity-routes.js.map +1 -0
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +2 -0
- package/dist/server/app.js.map +1 -1
- package/dist/server/bridge/__tests__/chat-handler.test.js +2 -16
- package/dist/server/bridge/__tests__/chat-handler.test.js.map +1 -1
- package/dist/server/bridge/__tests__/chat-integration.test.js +2 -16
- package/dist/server/bridge/__tests__/chat-integration.test.js.map +1 -1
- package/dist/server/bridge/chat-handler.d.ts.map +1 -1
- package/dist/server/bridge/chat-handler.js +18 -0
- package/dist/server/bridge/chat-handler.js.map +1 -1
- package/dist/server/db/schema.d.ts +1 -1
- package/dist/server/db/schema.d.ts.map +1 -1
- package/dist/server/db/schema.js +20 -0
- package/dist/server/db/schema.js.map +1 -1
- package/dist/server/services/activity-service.d.ts +35 -0
- package/dist/server/services/activity-service.d.ts.map +1 -0
- package/dist/server/services/activity-service.js +92 -0
- package/dist/server/services/activity-service.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
describe('CLI', () => {
|
|
5
|
+
const cliPath = path.resolve(__dirname, '../../bin/expxagents.js');
|
|
6
|
+
it('shows help output with all commands', () => {
|
|
7
|
+
execSync('npm run build', { cwd: path.resolve(__dirname, '../..') });
|
|
8
|
+
const output = execSync(`node ${cliPath} --help`, { encoding: 'utf-8' });
|
|
9
|
+
expect(output).toContain('expxagents');
|
|
10
|
+
expect(output).toContain('init');
|
|
11
|
+
expect(output).toContain('create');
|
|
12
|
+
expect(output).toContain('run');
|
|
13
|
+
expect(output).toContain('stop');
|
|
14
|
+
expect(output).toContain('list');
|
|
15
|
+
expect(output).toContain('install');
|
|
16
|
+
expect(output).toContain('uninstall');
|
|
17
|
+
expect(output).toContain('server');
|
|
18
|
+
});
|
|
19
|
+
it('shows version', () => {
|
|
20
|
+
const output = execSync(`node ${cliPath} --version`, { encoding: 'utf-8' });
|
|
21
|
+
expect(output.trim()).toMatch(/^\d+\.\d+\.\d+$/);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createCommand(description?: string): Promise<void>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { getCoreAsset } from '../utils/config.js';
|
|
5
|
+
export async function createCommand(description) {
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
const architectPath = getCoreAsset('solution-architect.agent.md');
|
|
8
|
+
const companyPath = path.join(cwd, '_expxagents', '_memory', 'company.md');
|
|
9
|
+
const prefsPath = path.join(cwd, '_expxagents', '_memory', 'preferences.md');
|
|
10
|
+
if (!fs.existsSync(architectPath)) {
|
|
11
|
+
console.error('Architect prompt not found. Package may be corrupted — reinstall expxagents.');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const architectPrompt = fs.readFileSync(architectPath, 'utf-8');
|
|
15
|
+
// Load context
|
|
16
|
+
let context = '';
|
|
17
|
+
if (fs.existsSync(companyPath)) {
|
|
18
|
+
const company = fs.readFileSync(companyPath, 'utf-8');
|
|
19
|
+
if (!company.includes('NOT CONFIGURED')) {
|
|
20
|
+
context += '\n## Company Context\n\n' + company;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (fs.existsSync(prefsPath)) {
|
|
24
|
+
context += '\n## User Preferences\n\n' + fs.readFileSync(prefsPath, 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
// Load Insight Hunter from package assets
|
|
27
|
+
const hunterPath = getCoreAsset('prompts/insight-hunter.prompt.md');
|
|
28
|
+
if (fs.existsSync(hunterPath)) {
|
|
29
|
+
context += '\n## Insight Hunter Instructions\n\n' + fs.readFileSync(hunterPath, 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
const fullPrompt = architectPrompt + context + (description ? `\n\n## User Request\n\n${description}` : '');
|
|
32
|
+
const squadsDir = path.join(cwd, 'squads');
|
|
33
|
+
if (!fs.existsSync(squadsDir)) {
|
|
34
|
+
fs.mkdirSync(squadsDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
console.log('Starting Solution Architect...\n');
|
|
37
|
+
const child = spawn('claude', ['-p', fullPrompt], {
|
|
38
|
+
cwd: squadsDir,
|
|
39
|
+
stdio: 'inherit',
|
|
40
|
+
});
|
|
41
|
+
child.on('error', (err) => {
|
|
42
|
+
console.error(`Failed to start Claude Code: ${err.message}`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
});
|
|
45
|
+
child.on('exit', (code) => {
|
|
46
|
+
if (code === 0) {
|
|
47
|
+
console.log('\nSquad created! Run `expxagents list` to see it.');
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.error(`\nArchitect exited with code ${code}`);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function doctorCommand(): Promise<void>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { getAssetsDir } from '../utils/config.js';
|
|
5
|
+
export async function doctorCommand() {
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
const checks = [];
|
|
8
|
+
// Node.js version
|
|
9
|
+
const nodeVersion = process.version;
|
|
10
|
+
const major = parseInt(nodeVersion.slice(1));
|
|
11
|
+
checks.push({
|
|
12
|
+
name: 'Node.js',
|
|
13
|
+
status: major >= 20 ? 'ok' : 'fail',
|
|
14
|
+
message: `${nodeVersion} ${major >= 20 ? '(meets >=20)' : '(requires >=20)'}`,
|
|
15
|
+
});
|
|
16
|
+
// Claude Code CLI
|
|
17
|
+
try {
|
|
18
|
+
const claudeVersion = execSync('claude --version', { encoding: 'utf-8' }).trim();
|
|
19
|
+
checks.push({ name: 'Claude Code CLI', status: 'ok', message: claudeVersion });
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
checks.push({ name: 'Claude Code CLI', status: 'fail', message: 'Not found — install from https://claude.ai/code' });
|
|
23
|
+
}
|
|
24
|
+
// Project structure
|
|
25
|
+
const requiredDirs = ['squads', '_expxagents/_memory'];
|
|
26
|
+
for (const dir of requiredDirs) {
|
|
27
|
+
const exists = fs.existsSync(path.join(cwd, dir));
|
|
28
|
+
checks.push({
|
|
29
|
+
name: `Directory: ${dir}`,
|
|
30
|
+
status: exists ? 'ok' : 'warn',
|
|
31
|
+
message: exists ? 'exists' : 'missing — run `expxagents init`',
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// .env file
|
|
35
|
+
const envExists = fs.existsSync(path.join(cwd, '.env'));
|
|
36
|
+
checks.push({
|
|
37
|
+
name: '.env file',
|
|
38
|
+
status: envExists ? 'ok' : 'warn',
|
|
39
|
+
message: envExists ? 'exists' : 'missing — run `expxagents init`',
|
|
40
|
+
});
|
|
41
|
+
// Company profile
|
|
42
|
+
const companyPath = path.join(cwd, '_expxagents', '_memory', 'company.md');
|
|
43
|
+
if (fs.existsSync(companyPath)) {
|
|
44
|
+
const content = fs.readFileSync(companyPath, 'utf-8');
|
|
45
|
+
const configured = !content.includes('NOT CONFIGURED');
|
|
46
|
+
checks.push({
|
|
47
|
+
name: 'Company profile',
|
|
48
|
+
status: configured ? 'ok' : 'warn',
|
|
49
|
+
message: configured ? 'configured' : 'not configured — run `expxagents onboarding`',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// Squads count
|
|
53
|
+
const squadsDir = path.join(cwd, 'squads');
|
|
54
|
+
if (fs.existsSync(squadsDir)) {
|
|
55
|
+
const squads = fs.readdirSync(squadsDir, { withFileTypes: true })
|
|
56
|
+
.filter(d => d.isDirectory() && !d.name.startsWith('.') && d.name !== '_memory')
|
|
57
|
+
.length;
|
|
58
|
+
checks.push({ name: 'Squads', status: 'ok', message: `${squads} found` });
|
|
59
|
+
}
|
|
60
|
+
// Package assets (check in package directory, not user project)
|
|
61
|
+
const assetsDir = getAssetsDir();
|
|
62
|
+
const coreFiles = [
|
|
63
|
+
{ label: 'solution-architect.agent.md', path: path.join(assetsDir, 'core', 'solution-architect.agent.md') },
|
|
64
|
+
{ label: 'runner.pipeline.md', path: path.join(assetsDir, 'core', 'runner.pipeline.md') },
|
|
65
|
+
{ label: 'agents catalog', path: path.join(assetsDir, 'agents', '_catalog.yaml') },
|
|
66
|
+
{ label: 'best-practices', path: path.join(assetsDir, 'core', 'best-practices', '_catalog.yaml') },
|
|
67
|
+
];
|
|
68
|
+
for (const file of coreFiles) {
|
|
69
|
+
const exists = fs.existsSync(file.path);
|
|
70
|
+
checks.push({
|
|
71
|
+
name: `Package: ${file.label}`,
|
|
72
|
+
status: exists ? 'ok' : 'warn',
|
|
73
|
+
message: exists ? 'present' : 'missing — reinstall expxagents',
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Display results
|
|
77
|
+
console.log('\n ExpxAgents System Diagnostics\n');
|
|
78
|
+
const symbols = { ok: ' OK', warn: 'WARN', fail: 'FAIL' };
|
|
79
|
+
let hasFailures = false;
|
|
80
|
+
for (const check of checks) {
|
|
81
|
+
if (check.status === 'fail')
|
|
82
|
+
hasFailures = true;
|
|
83
|
+
console.log(` [${symbols[check.status]}] ${check.name}: ${check.message}`);
|
|
84
|
+
}
|
|
85
|
+
console.log(hasFailures ? '\n Some checks failed. See above.\n' : '\n All checks passed!\n');
|
|
86
|
+
}
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import crypto from 'crypto';
|
|
4
|
+
import { getTemplateDir, getAssetsDir } from '../utils/config.js';
|
|
5
|
+
function getDefaultTemplate(file) {
|
|
6
|
+
if (file === 'company.md') {
|
|
7
|
+
return `<!-- NOT CONFIGURED -->
|
|
8
|
+
# Company Profile
|
|
9
|
+
|
|
10
|
+
## Company
|
|
11
|
+
- **Name:**
|
|
12
|
+
- **Website:**
|
|
13
|
+
- **Sector:**
|
|
14
|
+
- **Description:**
|
|
15
|
+
|
|
16
|
+
## Target Audience
|
|
17
|
+
- **Primary:**
|
|
18
|
+
- **Secondary:**
|
|
19
|
+
|
|
20
|
+
## Tone of Voice
|
|
21
|
+
- **Style:**
|
|
22
|
+
- **Keywords:**
|
|
23
|
+
|
|
24
|
+
## Social Media
|
|
25
|
+
- **Instagram:**
|
|
26
|
+
- **LinkedIn:**
|
|
27
|
+
- **Twitter:**
|
|
28
|
+
- **YouTube:**
|
|
29
|
+
|
|
30
|
+
## Products/Services
|
|
31
|
+
-
|
|
32
|
+
`;
|
|
33
|
+
}
|
|
34
|
+
if (file === 'preferences.md') {
|
|
35
|
+
return `# ExpxAgents Preferences
|
|
36
|
+
|
|
37
|
+
- **User Name:**
|
|
38
|
+
- **Language:** Portugues (Brasil)
|
|
39
|
+
- **IDE:** claude-code
|
|
40
|
+
- **Date Format:** DD/MM/YYYY
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
if (file === 'memories.md') {
|
|
44
|
+
return `# Squad Memories
|
|
45
|
+
|
|
46
|
+
> Updated automatically after each pipeline execution.
|
|
47
|
+
> Contains learnings, user preferences, and decisions from past runs.
|
|
48
|
+
|
|
49
|
+
## Execution History
|
|
50
|
+
|
|
51
|
+
(No runs yet)
|
|
52
|
+
|
|
53
|
+
## User Preferences
|
|
54
|
+
|
|
55
|
+
(No preferences recorded yet)
|
|
56
|
+
|
|
57
|
+
## Key Learnings
|
|
58
|
+
|
|
59
|
+
(No learnings recorded yet)
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Recursively copy a directory, skipping .DS_Store files.
|
|
66
|
+
*/
|
|
67
|
+
function copyDirRecursive(src, dest) {
|
|
68
|
+
if (!fs.existsSync(src))
|
|
69
|
+
return;
|
|
70
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
71
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
72
|
+
if (entry.name === '.DS_Store')
|
|
73
|
+
continue;
|
|
74
|
+
const srcPath = path.join(src, entry.name);
|
|
75
|
+
const destPath = path.join(dest, entry.name);
|
|
76
|
+
if (entry.isDirectory()) {
|
|
77
|
+
copyDirRecursive(srcPath, destPath);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
fs.copyFileSync(srcPath, destPath);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const SKILL_MD = `---
|
|
85
|
+
name: expxagents
|
|
86
|
+
description: "ExpxAgents \u2014 Multi-agent orchestration platform. Create and run AI squads with 93 specialized agents across 16 sectors."
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
# ExpxAgents \u2014 Multi-Agent Orchestration
|
|
90
|
+
|
|
91
|
+
You are now operating as the ExpxAgents system. Your primary role is to help users create, manage, and run AI agent squads.
|
|
92
|
+
|
|
93
|
+
## Initialization
|
|
94
|
+
|
|
95
|
+
On activation, perform these steps IN ORDER:
|
|
96
|
+
|
|
97
|
+
1. Read the company context: \`_expxagents/_memory/company.md\`
|
|
98
|
+
2. Read preferences: \`_expxagents/_memory/preferences.md\`
|
|
99
|
+
3. If company.md contains \`<!-- NOT CONFIGURED -->\` \u2192 trigger ONBOARDING
|
|
100
|
+
4. Otherwise \u2192 display MAIN MENU
|
|
101
|
+
|
|
102
|
+
## Onboarding Flow (first time only)
|
|
103
|
+
|
|
104
|
+
If company.md is not configured:
|
|
105
|
+
|
|
106
|
+
1. Welcome the user to ExpxAgents
|
|
107
|
+
2. Ask their name and preferred language
|
|
108
|
+
3. Ask company name, website URL, sector, description
|
|
109
|
+
4. If URL provided, use WebFetch + WebSearch to research the company
|
|
110
|
+
5. Present findings for confirmation
|
|
111
|
+
6. Save to \`_expxagents/_memory/company.md\` and \`_expxagents/_memory/preferences.md\`
|
|
112
|
+
7. Show main menu
|
|
113
|
+
|
|
114
|
+
## Main Menu
|
|
115
|
+
|
|
116
|
+
Present using AskUserQuestion with 2-4 options:
|
|
117
|
+
|
|
118
|
+
**Primary menu:**
|
|
119
|
+
- **Create a new squad** \u2014 Describe what you need and I'll design a squad
|
|
120
|
+
- **Run a squad** \u2014 Execute an existing squad's pipeline
|
|
121
|
+
- **My squads** \u2014 List, edit, or delete squads
|
|
122
|
+
- **More options** \u2014 Skills, company profile, settings
|
|
123
|
+
|
|
124
|
+
**More options submenu:**
|
|
125
|
+
- **Skills** \u2014 Browse, install, or create skills
|
|
126
|
+
- **Company profile** \u2014 View or edit company info
|
|
127
|
+
- **Settings** \u2014 Language, IDE, preferences
|
|
128
|
+
|
|
129
|
+
## Command Routing
|
|
130
|
+
|
|
131
|
+
| Command | Action |
|
|
132
|
+
|---------|--------|
|
|
133
|
+
| \`/expxagents\` | Show main menu |
|
|
134
|
+
| \`/expxagents create [description]\` | Load Solution Architect \u2192 Design squad |
|
|
135
|
+
| \`/expxagents run <name>\` | Load Release Manager \u2192 Execute pipeline |
|
|
136
|
+
| \`/expxagents list\` | List squads from \`squads/\` directory |
|
|
137
|
+
| \`/expxagents edit <name>\` | Load Solution Architect \u2192 Edit mode |
|
|
138
|
+
| \`/expxagents skills\` | Load Skills Engine \u2192 Show menu |
|
|
139
|
+
| \`/expxagents install <name>\` | Install skill from catalog |
|
|
140
|
+
| \`/expxagents uninstall <name>\` | Remove installed skill |
|
|
141
|
+
| \`/expxagents delete <name>\` | Confirm and delete squad |
|
|
142
|
+
| \`/expxagents dashboard\` | Run CLI to start server + open dashboard |
|
|
143
|
+
| \`/expxagents virtual-office\` | Run CLI to start server + open virtual office in browser |
|
|
144
|
+
| \`/expxagents help\` | Show help text |
|
|
145
|
+
|
|
146
|
+
## Virtual Office / Dashboard
|
|
147
|
+
|
|
148
|
+
When the user requests \`/expxagents virtual-office\` or \`/expxagents dashboard\`:
|
|
149
|
+
|
|
150
|
+
1. **ALWAYS run the CLI command** — do NOT generate HTML files or static pages
|
|
151
|
+
2. Execute: \`npx expxagents virtual-office\` via the Bash tool
|
|
152
|
+
3. This starts the Fastify server with the Pixi.js animated office dashboard and opens the browser
|
|
153
|
+
4. The server runs on port 3001 (or PORT env var) and serves the React SPA with WebSocket support
|
|
154
|
+
5. NEVER create static HTML files for the virtual office — the office is a full server-side application
|
|
155
|
+
|
|
156
|
+
## Loading Agents
|
|
157
|
+
|
|
158
|
+
When a core agent needs to be activated:
|
|
159
|
+
|
|
160
|
+
1. **Solution Architect:** Read \`_expxagents/core/solution-architect.agent.md\`
|
|
161
|
+
2. **Release Manager:** Read \`_expxagents/core/runner.pipeline.md\`
|
|
162
|
+
3. **Skills Engine:** Read \`_expxagents/core/skills.engine.md\`
|
|
163
|
+
4. **Insight Hunter:** Read \`_expxagents/core/prompts/insight-hunter.prompt.md\`
|
|
164
|
+
|
|
165
|
+
Adopt the agent's persona and follow its instructions completely.
|
|
166
|
+
|
|
167
|
+
## Agent Catalog
|
|
168
|
+
|
|
169
|
+
The full agent catalog is at \`agents/_catalog.yaml\`. Read it to see all available agents organized by sector:
|
|
170
|
+
|
|
171
|
+
- **Core (4):** solution-architect, release-manager, platform-engineer, insight-hunter
|
|
172
|
+
- **Development (18):** tech-lead, qa-engineer, devops-engineer, code-reviewer, backend-developer, frontend-developer, ux-design-expert, product-manager, ux-designer, business-analyst, scrum-master, dba, security-analyst, tech-writer, desktop-developer, ios-developer, android-developer, cross-platform-mobile
|
|
173
|
+
- **Implantation (5):** deployment-manager, environment-specialist, migration-specialist, integration-specialist, go-live-coordinator
|
|
174
|
+
- **Support (5):** l1-support, l2-support, l3-support, knowledge-base-manager, sla-monitor
|
|
175
|
+
- **Training (4):** training-designer, onboarding-coach, assessment-creator, workshop-facilitator
|
|
176
|
+
- **Finance (4):** billing-analyst, financial-controller, accounts-manager, budget-planner
|
|
177
|
+
- **HR (6):** recruiter, interview-coordinator, hr-onboarding, performance-analyst, benefits-manager, people-culture
|
|
178
|
+
- **Customer Success (5):** csm, churn-prevention, expansion-manager, nps-analyst, renewal-manager
|
|
179
|
+
- **Administrative (4):** procurement-specialist, document-controller, office-manager, process-documentation-officer
|
|
180
|
+
- **Marketing (8):** content-creator, seo-specialist, social-media-manager, email-marketing, paid-ads-manager, marketing-analyst, brand-guardian, landing-page-builder
|
|
181
|
+
- **Commercial (5):** sdr, account-executive, proposal-writer, crm-manager, pricing-strategist
|
|
182
|
+
- **R&D (5):** market-researcher, innovation-scout, prototype-builder, benchmark-analyst, product-analyst
|
|
183
|
+
- **Board (6):** strategic-advisor, okr-manager, board-report-writer, risk-analyst, governance-officer, business-intelligence
|
|
184
|
+
- **Accounting (6):** accountant, tax-compliance, fiscal-analyst, payroll-specialist, audit-analyst, financial-reporting
|
|
185
|
+
- **Legal (4):** contract-manager, legal-counsel, ip-specialist, labor-attorney
|
|
186
|
+
- **Compliance (4):** compliance-officer, data-privacy-specialist, regulatory-monitor, internal-auditor
|
|
187
|
+
|
|
188
|
+
When creating squads, use these agent templates as base for squad agents.
|
|
189
|
+
|
|
190
|
+
## Best Practices
|
|
191
|
+
|
|
192
|
+
Best-practice guides are at \`_expxagents/core/best-practices/\`. Read the catalog at \`_expxagents/core/best-practices/_catalog.yaml\` for available formats (landing-page, blog-post, email-sales, etc.).
|
|
193
|
+
|
|
194
|
+
## Running a Squad
|
|
195
|
+
|
|
196
|
+
1. Read \`squads/<name>/squad.yaml\`
|
|
197
|
+
2. Read \`squads/<name>/squad-party.csv\` (if exists)
|
|
198
|
+
3. Load company context from \`_expxagents/_memory/company.md\`
|
|
199
|
+
4. Load squad memory from \`squads/<name>/_memory/memories.md\`
|
|
200
|
+
5. Read runner instructions from \`_expxagents/core/runner.pipeline.md\`
|
|
201
|
+
6. Execute pipeline step by step
|
|
202
|
+
|
|
203
|
+
## Language
|
|
204
|
+
|
|
205
|
+
- Read preferences for user's language
|
|
206
|
+
- All output in user's language
|
|
207
|
+
- File names and code in English
|
|
208
|
+
|
|
209
|
+
## Help Text
|
|
210
|
+
|
|
211
|
+
\`\`\`
|
|
212
|
+
ExpxAgents \u2014 Multi-Agent Orchestration
|
|
213
|
+
|
|
214
|
+
SQUADS
|
|
215
|
+
/expxagents create Design a new squad
|
|
216
|
+
/expxagents run <name> Execute a squad pipeline
|
|
217
|
+
/expxagents list List all squads
|
|
218
|
+
/expxagents edit <name> Modify a squad
|
|
219
|
+
/expxagents delete <name> Delete a squad
|
|
220
|
+
|
|
221
|
+
SKILLS
|
|
222
|
+
/expxagents skills Browse skills
|
|
223
|
+
/expxagents install Install a skill
|
|
224
|
+
/expxagents uninstall Remove a skill
|
|
225
|
+
|
|
226
|
+
SETTINGS
|
|
227
|
+
/expxagents dashboard Open virtual office
|
|
228
|
+
/expxagents virtual-office Open virtual office in browser
|
|
229
|
+
/expxagents help Show this help
|
|
230
|
+
\`\`\`
|
|
231
|
+
|
|
232
|
+
## Critical Rules
|
|
233
|
+
|
|
234
|
+
- NEVER use the names "Leticia" or "Rafael" for agents, squads, personas, or any generated content — these names are permanently banned
|
|
235
|
+
- NEVER skip onboarding if company.md is not configured
|
|
236
|
+
- ALWAYS load company context before squad operations
|
|
237
|
+
- ALWAYS present checkpoints to user \u2014 never skip them
|
|
238
|
+
- ALWAYS save outputs and update squad memories
|
|
239
|
+
- When switching agent personas, indicate who is speaking
|
|
240
|
+
- AskUserQuestion must always have 2-4 options
|
|
241
|
+
`;
|
|
242
|
+
export async function initCommand(options = {}) {
|
|
243
|
+
const cwd = process.cwd();
|
|
244
|
+
const update = options.update ?? false;
|
|
245
|
+
if (update) {
|
|
246
|
+
console.log('Updating ExpxAgents assets...\n');
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
console.log('Initializing ExpxAgents project...\n');
|
|
250
|
+
}
|
|
251
|
+
// Create squads directory
|
|
252
|
+
const squadsDir = path.join(cwd, 'squads');
|
|
253
|
+
if (!fs.existsSync(squadsDir)) {
|
|
254
|
+
fs.mkdirSync(squadsDir, { recursive: true });
|
|
255
|
+
console.log(' Created squads/');
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
console.log(' squads/ already exists');
|
|
259
|
+
}
|
|
260
|
+
// Create _expxagents/_memory/ directory
|
|
261
|
+
const memoryDir = path.join(cwd, '_expxagents', '_memory');
|
|
262
|
+
if (!fs.existsSync(memoryDir)) {
|
|
263
|
+
fs.mkdirSync(memoryDir, { recursive: true });
|
|
264
|
+
console.log(' Created _expxagents/_memory/');
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
console.log(' _expxagents/_memory/ already exists');
|
|
268
|
+
}
|
|
269
|
+
// Copy template files from package assets
|
|
270
|
+
const templateDir = getTemplateDir();
|
|
271
|
+
const templateMemoryDir = path.join(templateDir, '_expxagents', '_memory');
|
|
272
|
+
const memoryFiles = ['company.md', 'preferences.md'];
|
|
273
|
+
for (const file of memoryFiles) {
|
|
274
|
+
const destPath = path.join(memoryDir, file);
|
|
275
|
+
if (!fs.existsSync(destPath)) {
|
|
276
|
+
const templateSrc = path.join(templateMemoryDir, file);
|
|
277
|
+
if (fs.existsSync(templateSrc)) {
|
|
278
|
+
fs.copyFileSync(templateSrc, destPath);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
fs.writeFileSync(destPath, getDefaultTemplate(file), 'utf-8');
|
|
282
|
+
}
|
|
283
|
+
console.log(` Created _expxagents/_memory/${file}`);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
console.log(` _expxagents/_memory/${file} already exists`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Copy core agents from package assets
|
|
290
|
+
const assetsDir = getAssetsDir();
|
|
291
|
+
const coreSrc = path.join(assetsDir, 'core');
|
|
292
|
+
const coreDest = path.join(cwd, '_expxagents', 'core');
|
|
293
|
+
if (update || !fs.existsSync(coreDest)) {
|
|
294
|
+
copyDirRecursive(coreSrc, coreDest);
|
|
295
|
+
console.log(update
|
|
296
|
+
? ' Updated _expxagents/core/ (core agents + best practices)'
|
|
297
|
+
: ' Copied _expxagents/core/ (core agents + best practices)');
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
console.log(' _expxagents/core/ already exists (use --update to refresh)');
|
|
301
|
+
}
|
|
302
|
+
// Copy agent catalog from package assets
|
|
303
|
+
const agentsSrc = path.join(assetsDir, 'agents');
|
|
304
|
+
const agentsDest = path.join(cwd, 'agents');
|
|
305
|
+
if (update || !fs.existsSync(agentsDest)) {
|
|
306
|
+
copyDirRecursive(agentsSrc, agentsDest);
|
|
307
|
+
console.log(update
|
|
308
|
+
? ' Updated agents/ (93 agent templates across 16 sectors)'
|
|
309
|
+
: ' Copied agents/ (93 agent templates across 16 sectors)');
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
console.log(' agents/ already exists (use --update to refresh)');
|
|
313
|
+
}
|
|
314
|
+
// Create/update Claude Code skill (.claude/skills/expxagents/SKILL.md)
|
|
315
|
+
const skillDir = path.join(cwd, '.claude', 'skills', 'expxagents');
|
|
316
|
+
const skillPath = path.join(skillDir, 'SKILL.md');
|
|
317
|
+
if (update || !fs.existsSync(skillPath)) {
|
|
318
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
319
|
+
fs.writeFileSync(skillPath, SKILL_MD, 'utf-8');
|
|
320
|
+
console.log(update
|
|
321
|
+
? ' Updated .claude/skills/expxagents/SKILL.md'
|
|
322
|
+
: ' Created .claude/skills/expxagents/SKILL.md (enables /expxagents command)');
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
console.log(' .claude/skills/expxagents/SKILL.md already exists (use --update to refresh)');
|
|
326
|
+
}
|
|
327
|
+
// Create squads/_memory/ subdirectory
|
|
328
|
+
const squadsMemoryDir = path.join(cwd, 'squads', '_memory');
|
|
329
|
+
if (!fs.existsSync(squadsMemoryDir)) {
|
|
330
|
+
fs.mkdirSync(squadsMemoryDir, { recursive: true });
|
|
331
|
+
console.log(' Created squads/_memory/');
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
console.log(' squads/_memory/ already exists');
|
|
335
|
+
}
|
|
336
|
+
const memoriesTemplateSrc = path.join(templateDir, 'squads', '_memory', 'memories.md');
|
|
337
|
+
const memoriesTemplateDest = path.join(squadsMemoryDir, 'memories.md');
|
|
338
|
+
if (!fs.existsSync(memoriesTemplateDest)) {
|
|
339
|
+
if (fs.existsSync(memoriesTemplateSrc)) {
|
|
340
|
+
fs.copyFileSync(memoriesTemplateSrc, memoriesTemplateDest);
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
fs.writeFileSync(memoriesTemplateDest, getDefaultTemplate('memories.md'), 'utf-8');
|
|
344
|
+
}
|
|
345
|
+
console.log(' Created squads/_memory/memories.md');
|
|
346
|
+
}
|
|
347
|
+
// Create .env if it doesn't exist
|
|
348
|
+
const envPath = path.join(cwd, '.env');
|
|
349
|
+
if (!fs.existsSync(envPath)) {
|
|
350
|
+
const jwtSecret = crypto.randomBytes(32).toString('hex');
|
|
351
|
+
const envContent = `JWT_SECRET=${jwtSecret}
|
|
352
|
+
PORT=3001
|
|
353
|
+
CORS_ORIGIN=http://localhost:3001
|
|
354
|
+
NODE_ENV=development
|
|
355
|
+
BRIDGE_TIMEOUT_MS=300000
|
|
356
|
+
`;
|
|
357
|
+
fs.writeFileSync(envPath, envContent, 'utf-8');
|
|
358
|
+
console.log(' Created .env with generated JWT_SECRET');
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
console.log(' .env already exists');
|
|
362
|
+
}
|
|
363
|
+
// Create .gitignore additions
|
|
364
|
+
const gitignorePath = path.join(cwd, '.gitignore');
|
|
365
|
+
const gitignoreEntries = [
|
|
366
|
+
'node_modules/',
|
|
367
|
+
'.env',
|
|
368
|
+
'*.tmp',
|
|
369
|
+
'squads/*/state.json',
|
|
370
|
+
'squads/*/state.json.tmp',
|
|
371
|
+
'squads/*/output/',
|
|
372
|
+
];
|
|
373
|
+
if (fs.existsSync(gitignorePath)) {
|
|
374
|
+
const existing = fs.readFileSync(gitignorePath, 'utf-8');
|
|
375
|
+
const toAdd = gitignoreEntries.filter(e => !existing.includes(e));
|
|
376
|
+
if (toAdd.length > 0) {
|
|
377
|
+
fs.appendFileSync(gitignorePath, '\n# ExpxAgents\n' + toAdd.join('\n') + '\n');
|
|
378
|
+
console.log(' Updated .gitignore');
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
fs.writeFileSync(gitignorePath, gitignoreEntries.join('\n') + '\n', 'utf-8');
|
|
383
|
+
console.log(' Created .gitignore');
|
|
384
|
+
}
|
|
385
|
+
console.log('\nProject initialized! Run `expxagents onboarding` to configure your profile.');
|
|
386
|
+
console.log('Use /expxagents in Claude Code to get started.');
|
|
387
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function installCommand(skillName: string): Promise<void>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const SKILL_CATALOG = {
|
|
4
|
+
'web-search': {
|
|
5
|
+
description: 'Web search capability (built-in)',
|
|
6
|
+
type: 'prompt',
|
|
7
|
+
template: `---\nname: web-search\ndescription: "Search the web for information"\ntype: prompt\nversion: "1.0.0"\ncategories: [search, research]\n---\n\n# Web Search\n\nUse the built-in web_search tool to find information online.\n`,
|
|
8
|
+
},
|
|
9
|
+
'apify': {
|
|
10
|
+
description: 'Web scraping via Apify Actors',
|
|
11
|
+
type: 'mcp',
|
|
12
|
+
template: `---\nname: apify\ndescription: "Web scraping via Apify Actors"\ntype: mcp\nversion: "1.0.0"\nmcp:\n server_name: "apify"\n command: "npx"\n args: ["-y", "@apify/actors-mcp-server@latest"]\n transport: "stdio"\nenv:\n - APIFY_TOKEN\ncategories: [scraping, data]\n---\n\n# Apify\n\nUse Apify Actors for web scraping tasks.\n`,
|
|
13
|
+
},
|
|
14
|
+
'image-creator': {
|
|
15
|
+
description: 'AI image generation via DALL-E or Stable Diffusion',
|
|
16
|
+
type: 'mcp',
|
|
17
|
+
template: `---\nname: image-creator\ndescription: "Generate images using AI models"\ntype: mcp\nversion: "1.0.0"\nmcp:\n server_name: "image-creator"\n command: "npx"\n args: ["-y", "@modelcontextprotocol/server-dalle@latest"]\n transport: "stdio"\nenv:\n - OPENAI_API_KEY\ncategories: [design, content]\n---\n\n# Image Creator\n\nGenerate images using AI models for content creation.\n`,
|
|
18
|
+
},
|
|
19
|
+
'github': {
|
|
20
|
+
description: 'GitHub integration for repositories, issues, PRs',
|
|
21
|
+
type: 'mcp',
|
|
22
|
+
template: `---\nname: github\ndescription: "GitHub integration for repository management"\ntype: mcp\nversion: "1.0.0"\nmcp:\n server_name: "github"\n command: "npx"\n args: ["-y", "@modelcontextprotocol/server-github@latest"]\n transport: "stdio"\nenv:\n - GITHUB_TOKEN\ncategories: [development, integration]\n---\n\n# GitHub Integration\n\nManage GitHub repositories, issues, and pull requests.\n`,
|
|
23
|
+
},
|
|
24
|
+
'slack': {
|
|
25
|
+
description: 'Slack messaging integration',
|
|
26
|
+
type: 'mcp',
|
|
27
|
+
template: `---\nname: slack\ndescription: "Send and receive Slack messages"\ntype: mcp\nversion: "1.0.0"\nmcp:\n server_name: "slack"\n command: "npx"\n args: ["-y", "@anthropic/slack-mcp-server@latest"]\n transport: "stdio"\nenv:\n - SLACK_BOT_TOKEN\ncategories: [communication, integration]\n---\n\n# Slack Integration\n\nSend and receive messages via Slack.\n`,
|
|
28
|
+
},
|
|
29
|
+
'canva': {
|
|
30
|
+
description: 'Design creation via Canva API',
|
|
31
|
+
type: 'mcp',
|
|
32
|
+
template: `---\nname: canva\ndescription: "Create designs using Canva"\ntype: mcp\nversion: "1.0.0"\nmcp:\n server_name: "canva"\n command: "npx"\n args: ["-y", "@anthropic/canva-mcp-server@latest"]\n transport: "stdio"\nenv:\n - CANVA_API_KEY\ncategories: [design, content]\n---\n\n# Canva Integration\n\nCreate professional designs using Canva.\n`,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export async function installCommand(skillName) {
|
|
36
|
+
const cwd = process.cwd();
|
|
37
|
+
const skillsDir = path.join(cwd, 'skills');
|
|
38
|
+
if (!skillName) {
|
|
39
|
+
console.log('\n Available skills:\n');
|
|
40
|
+
for (const [name, info] of Object.entries(SKILL_CATALOG)) {
|
|
41
|
+
const installed = fs.existsSync(path.join(skillsDir, name));
|
|
42
|
+
console.log(` ${installed ? '[installed]' : ' '} ${name} — ${info.description}`);
|
|
43
|
+
}
|
|
44
|
+
console.log('\n Usage: expxagents install <skill-name>\n');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const skill = SKILL_CATALOG[skillName];
|
|
48
|
+
if (!skill) {
|
|
49
|
+
console.error(` Skill "${skillName}" not found in catalog.`);
|
|
50
|
+
console.log(' Run `expxagents install` to see available skills.');
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const skillDir = path.join(skillsDir, skillName);
|
|
54
|
+
if (fs.existsSync(skillDir)) {
|
|
55
|
+
console.log(` Skill "${skillName}" is already installed.`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
59
|
+
fs.writeFileSync(path.join(skillDir, 'SKILL.md'), skill.template, 'utf-8');
|
|
60
|
+
console.log(` Installed skill: ${skillName}`);
|
|
61
|
+
if (skill.type === 'mcp') {
|
|
62
|
+
console.log(`\n This skill requires MCP configuration.`);
|
|
63
|
+
console.log(` Check .mcp.json and set required environment variables.`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function jarvisCommand(): Promise<void>;
|