UNPKG

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
#!/usr/bin/env node /** * 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(); }