oneie
Version:
š¤ ONE Personal Collaborative Intelligence - Creates personalized AI workspace from your me.md profile. Simple: npx oneie ā edit me.md ā generate personalized agents, workflows & missions. From students to enterprises, ONE adapts to your context.
776 lines (659 loc) ⢠26.4 kB
JavaScript
/**
* ONE Personal Installer
* Creates personalized collaborative intelligence space based on me.md
*/
import fs from 'fs-extra';
import path from 'path';
import chalk from 'chalk';
import inquirer from 'inquirer';
import { MissionSystem } from './mission-system.js';
import { StorySystem } from './story-system.js';
import { TaskSystem } from './task-system.js';
import { AgentInstaller } from '../one/tools/agent-installer.js';
export class OneInstaller {
constructor(projectPath = process.cwd()) {
this.projectPath = projectPath;
this.oneDir = path.join(projectPath, '.one');
this.meFile = path.join(projectPath, 'me.md');
this.scaffoldDir = path.join(path.dirname(new URL(import.meta.url).pathname), '..', 'scaffold');
// Initialize agent installer for Claude Code integration
this.agentInstaller = new AgentInstaller({
sourceAgentsPath: path.join(path.dirname(new URL(import.meta.url).pathname), '..', 'one', 'agents'),
targetAgentsPath: path.join(projectPath, '.claude', 'agents'),
commandsPath: path.join(projectPath, '.claude', 'commands')
});
}
async install(options = {}) {
console.log(chalk.cyan.bold('\\nš ONE - Personal Collaborative Intelligence\\n'));
// Check if already installed (unless it's a marketing upgrade)
if (await this.isInstalled() && !options.includeMarketing) {
console.log(chalk.yellow('ā” ONE is already installed here!'));
console.log(chalk.gray('Use: npx oneie generate # Generate content from your me.md'));
console.log(chalk.gray('Use: npx oneie update-me # Edit your me.md profile'));
return;
}
// Special handling for marketing upgrade
if (options.includeMarketing && await this.isInstalled()) {
console.log(chalk.blue('šÆ Adding marketing team agents to existing installation...'));
await this.installClaudeCodeAgents(options);
console.log(chalk.green('\\nā
Marketing agents installation complete!'));
console.log(chalk.cyan('\\nš Try your new marketing agents:'));
console.log(' one:marketing-director "Create a marketing strategy"');
console.log(' one:marketing-viral-growth "Design viral content campaign"');
return;
}
try {
// Step 1: Welcome and explanation
await this.showWelcome();
// Step 2: Create me.md through guided questions
const profile = await this.createPersonalProfile(options);
// Step 3: Create .one directory structure
await this.createOneStructure();
// Step 4: Generate personalized content based on me.md
await this.generatePersonalizedContent(profile);
// Step 5: Install Claude Code agent system
await this.installClaudeCodeAgents(options);
// Step 6: Show next steps
await this.showCompletion();
} catch (error) {
console.error(chalk.red('ā Installation failed:'), error.message);
process.exit(1);
}
}
async isInstalled() {
return await fs.pathExists(this.oneDir) && await fs.pathExists(this.meFile);
}
async showWelcome() {
console.log(chalk.blue('š Welcome to ONE!'));
console.log('');
console.log('ONE creates a personalized collaborative workspace just for you.');
console.log('It reads your personal profile and generates:');
console.log(chalk.cyan(' ⢠AI agents tailored to your role and expertise'));
console.log(chalk.cyan(' ⢠Workflows that match your working style'));
console.log(chalk.cyan(' ⢠Templates for your industry and projects'));
console.log(chalk.cyan(' ⢠Mission/Story structure for your goals'));
console.log('');
console.log('Let\'s create your personal profile...');
console.log('');
}
async createPersonalProfile(options = {}) {
console.log(chalk.blue('š Creating Your Personal Profile'));
console.log('');
// Auto mode with default values
if (options.auto) {
const defaultProfile = {
name: 'Developer',
role: 'Software Developer',
experience: '3',
skills: ['JavaScript/TypeScript', 'React/Vue/Angular', 'Node.js'],
currentProject: 'Building a web application',
challenges: 'Learning new technologies and scaling the project',
company: 'Personal project',
companySize: 'Solo/Personal',
industry: 'Technology',
learningStyle: 'Hands-on examples and tutorials',
workStyle: 'Fast iteration and MVP approach'
};
const meContent = this.generateMeMarkdown(defaultProfile);
await fs.writeFile(this.meFile, meContent);
console.log(chalk.green('\\nā
Created default personal profile: me.md'));
console.log(chalk.gray('Edit me.md to customize your profile, then run: npx oneie generate'));
return defaultProfile;
}
const questions = [
{
type: 'input',
name: 'name',
message: 'What\'s your name?',
validate: input => input.length > 0 || 'Please enter your name'
},
{
type: 'input',
name: 'role',
message: 'What\'s your role/job title?',
default: 'Developer'
},
{
type: 'input',
name: 'experience',
message: 'How many years of experience do you have?',
default: '3'
},
{
type: 'checkbox',
name: 'skills',
message: 'What are your main skills/technologies?',
choices: [
'JavaScript/TypeScript',
'React/Vue/Angular',
'Node.js',
'Python',
'Java',
'C#/.NET',
'Go',
'Rust',
'AWS/Cloud',
'Docker/Kubernetes',
'Databases',
'Mobile Development',
'Machine Learning',
'DevOps',
'Design/UX',
'Project Management',
'Other'
]
},
{
type: 'input',
name: 'currentProject',
message: 'What are you currently working on?',
default: 'Building a web application'
},
{
type: 'input',
name: 'challenges',
message: 'What are your main challenges right now?',
default: 'Learning new technologies and scaling the project'
},
{
type: 'input',
name: 'company',
message: 'What company/organization do you work for?',
default: 'Personal project'
},
{
type: 'list',
name: 'companySize',
message: 'What\'s your company size?',
choices: [
'Solo/Personal',
'Startup (2-10 people)',
'Small company (11-50)',
'Medium company (51-200)',
'Large company (201-1000)',
'Enterprise (1000+)'
]
},
{
type: 'input',
name: 'industry',
message: 'What industry/domain do you work in?',
default: 'Technology'
},
{
type: 'list',
name: 'learningStyle',
message: 'How do you prefer to learn?',
choices: [
'Hands-on examples and tutorials',
'Documentation and written guides',
'Video content and demonstrations',
'Interactive coding and experimentation',
'Discussion and collaboration'
]
},
{
type: 'list',
name: 'workStyle',
message: 'What\'s your preferred working style?',
choices: [
'Fast iteration and MVP approach',
'Careful planning and documentation',
'Test-driven development',
'Agile/Scrum methodology',
'Flexible and adaptive'
]
}
];
const answers = await inquirer.prompt(questions);
// Create me.md content
const meContent = this.generateMeMarkdown(answers);
await fs.writeFile(this.meFile, meContent);
console.log(chalk.green('\\nā
Created your personal profile: me.md'));
return answers;
}
generateMeMarkdown(profile) {
return `# Me - ${profile.name}
## Personal Info
${profile.role} with ${profile.experience} years of experience
Industry: ${profile.industry}
Company: ${profile.company} (${profile.companySize})
### Skills & Technologies
${profile.skills.map(skill => `- ${skill}`).join('\\n')}
### Learning & Work Style
- Learning preference: ${profile.learningStyle}
- Work approach: ${profile.workStyle}
## Current Work
**Project:** ${profile.currentProject}
**Main Challenges:**
${profile.challenges}
## Goals
- Complete current project successfully
- Learn and grow technical skills
- Build effective workflows and processes
## Company Context
Working at ${profile.company} (${profile.companySize})
${profile.industry} industry focus
---
*This profile helps ONE create personalized agents, workflows, and templates just for you.*
*Edit this file anytime to update your ONE workspace.*
`;
}
async createOneStructure() {
console.log(chalk.blue('\\nšļø Creating .one workspace structure...'));
// Create directory structure
const dirs = [
'.one',
'.one/agents',
'.one/missions',
'.one/stories',
'.one/tasks',
'.one/workflows',
'.one/templates',
'.one/knowledge',
'.one/spaces'
];
for (const dir of dirs) {
await fs.ensureDir(path.join(this.projectPath, dir));
}
// Copy scaffold files if they exist
if (await fs.pathExists(this.scaffoldDir)) {
await fs.copy(this.scaffoldDir, this.oneDir, { overwrite: false });
}
console.log(chalk.green('ā
Created .one workspace structure'));
}
async generatePersonalizedContent(profile) {
console.log(chalk.blue('\\nš¤ Generating personalized content...'));
// Generate personalized agents
await this.generatePersonalAgents(profile);
// Generate workflow templates
await this.generateWorkflowTemplates(profile);
// Generate mission templates
await this.generateMissionTemplates(profile);
// Create initial space configuration
await this.createSpaceConfig(profile);
console.log(chalk.green('ā
Generated personalized content'));
}
async generatePersonalAgents(profile) {
const agents = [];
// Core agents everyone gets
agents.push({
name: 'Personal Assistant',
description: `Your personal AI assistant who knows about your role as ${profile.role} and your work in ${profile.industry}.`,
expertise: ['project coordination', 'personal productivity', profile.role.toLowerCase()],
context: profile
});
// Skill-based agents
if (profile.skills.includes('JavaScript/TypeScript')) {
agents.push({
name: 'JavaScript Specialist',
description: 'Expert in JavaScript/TypeScript development and modern frameworks.',
expertise: ['JavaScript', 'TypeScript', 'Node.js', 'web development'],
context: profile
});
}
if (profile.skills.includes('React/Vue/Angular')) {
agents.push({
name: 'Frontend Specialist',
description: 'React, Vue, and Angular expert for frontend development.',
expertise: ['React', 'Vue', 'Angular', 'frontend', 'UI/UX'],
context: profile
});
}
if (profile.skills.includes('Python')) {
agents.push({
name: 'Python Specialist',
description: 'Python development expert for backend and data work.',
expertise: ['Python', 'backend development', 'data analysis'],
context: profile
});
}
// Role-based agents
if (profile.role.toLowerCase().includes('manager') || profile.role.toLowerCase().includes('lead')) {
agents.push({
name: 'Team Leadership Advisor',
description: 'Guidance on team management, project coordination, and leadership.',
expertise: ['team management', 'project leadership', 'communication'],
context: profile
});
}
// Save agent configurations
for (const agent of agents) {
const agentFile = path.join(this.oneDir, 'agents', `${agent.name.toLowerCase().replace(/\\s+/g, '-')}.yaml`);
const agentConfig = {
name: agent.name,
description: agent.description,
expertise: agent.expertise,
personalContext: {
userRole: profile.role,
userSkills: profile.skills,
userIndustry: profile.industry,
userCompany: profile.company,
userWorkStyle: profile.workStyle,
userLearningStyle: profile.learningStyle
},
prompts: {
system: `You are ${agent.name}, specifically helping ${profile.name}, a ${profile.role} working in ${profile.industry}.
Adapt your communication style to their preference for ${profile.learningStyle.toLowerCase()} and their ${profile.workStyle.toLowerCase()} approach.
Their main skills: ${profile.skills.join(', ')}
Current focus: ${profile.currentProject}
Main challenges: ${profile.challenges}`,
greeting: `Hi ${profile.name}! I'm your ${agent.name}, here to help with your work as a ${profile.role}. What can I assist you with today?`
}
};
await fs.writeFile(agentFile, `---
name: ${agentConfig.name}
description: |
${agentConfig.description}
Personalized for ${profile.name} (${profile.role})
Context: ${profile.industry} industry, ${profile.company}
expertise: ${JSON.stringify(agentConfig.expertise)}
context: ${JSON.stringify(agentConfig.personalContext)}
---
# ${agent.name}
**Your personalized AI specialist for ${agent.expertise.join(', ')}**
## About You
I know you're ${profile.name}, working as a ${profile.role} at ${profile.company} in the ${profile.industry} industry.
You prefer ${profile.learningStyle.toLowerCase()} and work with a ${profile.workStyle.toLowerCase()} approach.
## How I Help
Based on your profile, I'm specialized to help you with:
${agent.expertise.map(skill => `- ${skill}`).join('\\n')}
## Your Context
- **Current Project:** ${profile.currentProject}
- **Main Challenges:** ${profile.challenges}
- **Skills:** ${profile.skills.join(', ')}
- **Experience:** ${profile.experience} years
I'll adapt my suggestions to match your experience level and preferred learning style.
`);
}
console.log(chalk.cyan(` ā Created ${agents.length} personalized agents`));
}
async generateWorkflowTemplates(profile) {
const workflows = [];
// Development workflows based on skills
if (profile.skills.some(skill => ['JavaScript/TypeScript', 'React/Vue/Angular', 'Node.js'].includes(skill))) {
workflows.push({
name: 'web-development-workflow',
title: 'Web Development Workflow',
description: `Personalized web development workflow for ${profile.name}`,
steps: [
'Project planning and requirements',
'Setup development environment',
'Implement core features',
'Testing and quality assurance',
'Deployment and monitoring'
],
tools: profile.skills.filter(skill =>
['JavaScript/TypeScript', 'React/Vue/Angular', 'Node.js', 'Docker/Kubernetes'].includes(skill)
),
adaptedFor: profile.workStyle
});
}
// Save workflow templates
for (const workflow of workflows) {
const workflowFile = path.join(this.oneDir, 'workflows', `${workflow.name}.yaml`);
await fs.writeFile(workflowFile, `name: ${workflow.name}
title: ${workflow.title}
description: ${workflow.description}
personalizedFor: ${profile.name}
userContext:
role: ${profile.role}
experience: ${profile.experience}
workStyle: ${profile.workStyle}
skills: ${JSON.stringify(profile.skills)}
steps:
${workflow.steps.map(step => ` - ${step}`).join('\\n')}
tools:
${workflow.tools.map(tool => ` - ${tool}`).join('\\n')}
adaptations:
workStyle: ${workflow.adaptedFor}
learningStyle: ${profile.learningStyle}
`);
}
console.log(chalk.cyan(` ā Created ${workflows.length} personalized workflows`));
}
async generateMissionTemplates(profile) {
// Create mission templates based on their current project and challenges
const missionTemplates = [
{
name: 'current-project-mission',
objective: profile.currentProject,
challenges: profile.challenges.split(',').map(c => c.trim()),
skills: profile.skills,
timeline: this.estimateProjectTimeline(profile),
personalContext: profile
},
{
name: 'skill-development-mission',
objective: `Develop advanced skills in ${profile.skills.slice(0, 3).join(', ')}`,
challenges: ['Learning new concepts', 'Applying knowledge practically', 'Building portfolio projects'],
skills: profile.skills,
timeline: '1-3 months',
personalContext: profile
}
];
for (const template of missionTemplates) {
const templateFile = path.join(this.oneDir, 'templates', `${template.name}.yaml`);
await fs.writeFile(templateFile, `name: ${template.name}
objective: ${template.objective}
personalizedFor: ${profile.name}
userContext:
role: ${profile.role}
company: ${profile.company}
industry: ${profile.industry}
experience: ${profile.experience}
challenges:
${template.challenges.map(challenge => ` - ${challenge}`).join('\\n')}
requiredSkills:
${template.skills.slice(0, 5).map(skill => ` - ${skill}`).join('\\n')}
estimatedTimeline: ${template.timeline}
workStyle: ${profile.workStyle}
learningStyle: ${profile.learningStyle}
suggestedStories:
- "Plan and design ${template.objective}"
- "Research and learn required technologies"
- "Implement core functionality"
- "Test and validate solution"
- "Deploy and document results"
`);
}
console.log(chalk.cyan(` ā Created ${missionTemplates.length} personalized mission templates`));
}
estimateProjectTimeline(profile) {
const experience = parseInt(profile.experience) || 1;
const complexity = profile.currentProject.toLowerCase();
if (complexity.includes('simple') || complexity.includes('basic')) {
return experience > 5 ? '1-2 weeks' : '2-4 weeks';
} else if (complexity.includes('complex') || complexity.includes('enterprise')) {
return experience > 5 ? '2-3 months' : '3-6 months';
} else {
return experience > 5 ? '3-6 weeks' : '6-8 weeks';
}
}
async createSpaceConfig(profile) {
const spaceConfig = {
version: '1.0.0',
personalSpace: {
owner: profile.name,
role: profile.role,
company: profile.company,
industry: profile.industry,
created: new Date().toISOString()
},
preferences: {
workStyle: profile.workStyle,
learningStyle: profile.learningStyle,
primarySkills: profile.skills.slice(0, 5)
},
agents: {
active: ['personal-assistant'],
available: []
},
defaultWorkflows: [
'web-development-workflow'
],
missionTemplates: [
'current-project-mission',
'skill-development-mission'
]
};
const yaml = await import('js-yaml');
await fs.writeFile(
path.join(this.oneDir, 'spaces', 'personal.yaml'),
`# Personal Space Configuration for ${profile.name}
${yaml.default.dump(spaceConfig, { indent: 2 })}`
);
console.log(chalk.cyan(' ā Created personal space configuration'));
}
async installClaudeCodeAgents(options = {}) {
console.log(chalk.blue('\nš Setting up Claude Code integration...'));
try {
// Install agents with selective installation based on options
const installOptions = {
coreOnly: options.coreOnly || false,
includeMarketing: options.includeMarketing || false,
includeTrialLicense: options.trial || false
};
await this.agentInstaller.install(installOptions);
// Create trial license if requested
if (options.trial) {
console.log(chalk.blue('šÆ Setting up trial license...'));
const licenseValidator = this.agentInstaller.licenseValidator;
await licenseValidator.createTrialLicense(7);
console.log(chalk.green('ā
7-day trial license created'));
}
} catch (error) {
console.log(chalk.yellow('ā ļø Claude Code integration setup failed:', error.message));
console.log(chalk.gray('You can install agents later with: npx oneie agents install'));
}
}
async showCompletion() {
console.log(chalk.green.bold('\\nš ONE Installation Complete!\\n'));
console.log(chalk.blue('š Created:'));
console.log(' me.md # Your personal profile');
console.log(' .one/agents/ # Your personalized AI agents');
console.log(' .one/workflows/ # Workflows for your work style');
console.log(' .one/templates/ # Mission templates for your goals');
console.log(' .one/spaces/ # Your personal collaborative space');
console.log(' .claude/agents/ # Claude Code integrated agents');
console.log(' .claude/commands/ # Agent command files for Claude Code');
console.log(chalk.yellow('\\nš Next Steps:'));
console.log(' npx oneie generate # Generate content from your me.md');
console.log(' npx oneie mission create # Start your first mission');
console.log(' npx oneie agents # Meet your personal agents');
console.log(' npx oneie update-me # Update your profile anytime');
console.log(chalk.cyan('\\nš¤ Claude Code Integration:'));
console.log(' one:engineering-director # Access agents in Claude Code');
console.log(' one:license --status # Check premium agent access');
console.log(' one:license --trial # Try premium agents (7 days)');
console.log(chalk.gray('\\nš” Your workspace adapts as you update me.md'));
console.log(chalk.gray(' Add new skills, projects, or goals and regenerate content.'));
}
async generate() {
console.log(chalk.cyan.bold('\\nš Generating Content from Your Profile\\n'));
if (!await this.isInstalled()) {
console.log(chalk.red('ā ONE is not installed here.'));
console.log(chalk.gray('Run: npx oneie'));
return;
}
// Read current me.md
const meContent = await fs.readFile(this.meFile, 'utf8');
const profile = this.parseProfileFromMarkdown(meContent);
console.log(chalk.blue(`š Hi ${profile.name || 'there'}!`));
console.log(chalk.gray(`Reading your profile: ${profile.role} at ${profile.company}`));
// Regenerate personalized content
await this.generatePersonalizedContent(profile);
console.log(chalk.green('\\nā
Content regenerated based on your current me.md'));
console.log(chalk.cyan('Your agents, workflows, and templates are now up to date!'));
}
parseProfileFromMarkdown(content) {
// Simple markdown parser to extract profile info
const lines = content.split('\\n');
const profile = {
name: '',
role: '',
company: '',
industry: '',
skills: [],
experience: '',
workStyle: '',
learningStyle: '',
currentProject: '',
challenges: ''
};
let currentSection = '';
for (const line of lines) {
if (line.startsWith('# Me - ')) {
profile.name = line.replace('# Me - ', '').trim();
} else if (line.includes('Industry:')) {
profile.industry = line.split('Industry:')[1]?.trim() || '';
} else if (line.includes('Company:')) {
profile.company = line.split('Company:')[1]?.split('(')[0]?.trim() || '';
} else if (line.includes('**Project:**')) {
profile.currentProject = line.split('**Project:**')[1]?.trim() || '';
} else if (line.includes('**Main Challenges:**')) {
currentSection = 'challenges';
} else if (currentSection === 'challenges' && line.trim() && !line.startsWith('#')) {
profile.challenges = line.trim();
currentSection = '';
}
}
return profile;
}
async updateMe() {
console.log(chalk.cyan.bold('\\nāļø Update Your Personal Profile\\n'));
if (!await this.isInstalled()) {
console.log(chalk.red('ā ONE is not installed here.'));
console.log(chalk.gray('Run: npx oneie'));
return;
}
// Read current me.md
const meContent = await fs.readFile(this.meFile, 'utf8');
console.log(chalk.blue('Current me.md:'));
console.log(chalk.gray(meContent.substring(0, 200) + '...'));
console.log('');
const { action } = await inquirer.prompt([
{
type: 'list',
name: 'action',
message: 'What would you like to do?',
choices: [
'Edit me.md in your default editor',
'Update profile through questions',
'View current profile',
'Regenerate content after changes'
]
}
]);
if (action === 'Edit me.md in your default editor') {
console.log(chalk.cyan('Opening me.md in your default editor...'));
console.log(chalk.gray('Save and close the file when done, then run: npx oneie generate'));
const { spawn } = await import('child_process');
const editor = process.env.EDITOR || 'nano';
spawn(editor, [this.meFile], { stdio: 'inherit' });
} else if (action === 'Update profile through questions') {
const profile = await this.createPersonalProfile({ skipWelcome: true });
console.log(chalk.green('\\nā
Profile updated!'));
console.log(chalk.cyan('Run: npx oneie generate # To update your workspace'));
} else if (action === 'View current profile') {
console.log(chalk.blue('\\nš Your Current Profile:\\n'));
console.log(meContent);
} else if (action === 'Regenerate content after changes') {
await this.generate();
}
}
}
// CLI functions
export async function install(options = {}) {
const installer = new OneInstaller();
return await installer.install(options);
}
export async function generate() {
const installer = new OneInstaller();
return await installer.generate();
}
export async function updateMe() {
const installer = new OneInstaller();
return await installer.updateMe();
}