tycono 0.1.7 → 0.1.8
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/README.md +3 -8
- package/bin/tycono.ts +0 -9
- package/package.json +1 -1
- package/src/api/src/routes/git.ts +179 -0
- package/src/api/src/routes/speech.ts +29 -0
- package/src/api/src/routes/sync.ts +165 -0
- package/src/api/src/services/scaffold.ts +1 -1
- package/src/api/src/utils/role-level.ts +30 -0
- package/src/web/dist/assets/index-BxDf0CSf.css +1 -0
- package/src/web/dist/assets/index-FesWAu2a.js +95 -0
- package/src/web/dist/assets/{preview-app-pniQIcGk.js → preview-app-DfJ0nbgX.js} +1 -1
- package/src/web/dist/index.html +2 -2
- package/bin/init.ts +0 -306
- package/src/web/dist/assets/index-CZtcQkJ_.js +0 -95
- package/src/web/dist/assets/index-DIjVGqFh.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as s,g as m,a as S,j as t,S as y,P as C,b as j,H as v,c as R,d as k,e as E,f as w,h as B}from"./index-
|
|
1
|
+
import{r as s,g as m,a as S,j as t,S as y,P as C,b as j,H as v,c as R,d as k,e as E,f as w,h as B}from"./index-FesWAu2a.js";function A({id:i,ap:a,bobY:r,layers:l}){const c=s.useRef(null),o=k(i);return s.useEffect(()=>{if(!o||!c.current)return;const p=c.current.getContext("2d");if(!p)return;const h={...o,layers:o.layers.filter(u=>l.has(u.name))};E(p,h,r,a)},[o,a,r,l]),o?t.jsxs("div",{style:{background:"#161b22",border:"1px solid #21262d",borderRadius:8,padding:16,textAlign:"center",minWidth:140},children:[t.jsx("canvas",{ref:c,width:o.width*2,height:o.height*2,style:{imageRendering:"pixelated",display:"block",margin:"0 auto 8px",width:o.width*6,height:o.height*6,border:"1px solid #30363d",background:"#0d1117"}}),t.jsx("div",{style:{fontSize:11,color:"#8b949e",textTransform:"uppercase",letterSpacing:1},children:i})]}):null}function F({id:i}){const a=s.useRef(null),r=w(i);return s.useEffect(()=>{if(!r||!a.current)return;const l=a.current.getContext("2d");l&&B(l,r)},[r]),r?t.jsxs("div",{style:{background:"#161b22",border:"1px solid #21262d",borderRadius:8,padding:16,textAlign:"center"},children:[t.jsx("canvas",{ref:a,width:r.canvasWidth,height:r.canvasHeight,style:{imageRendering:"pixelated",display:"block",margin:"0 auto 8px",width:r.canvasWidth*2,height:r.canvasHeight*2,border:"1px solid #30363d",background:"#0d1117"}}),t.jsx("div",{style:{fontSize:11,color:"#8b949e",textTransform:"uppercase",letterSpacing:1},children:i})]}):null}const g=["body","hair","face","accessory","item","legs"];function I(){const[i,a]=s.useState({skinColor:"#F5CBA7",hairColor:"#2C1810",shirtColor:"#1565C0",pantsColor:"#37474F",shoeColor:"#212121"}),[r,l]=s.useState(new Set(g)),[c,o]=s.useState(0),p=s.useRef(0);s.useEffect(()=>{const e=()=>{p.current++,o(p.current%60<30?1:0),requestAnimationFrame(e)},n=requestAnimationFrame(e);return()=>cancelAnimationFrame(n)},[]);const h=m(),u=S(),x=s.useCallback(e=>{l(n=>{const d=new Set(n);return d.has(e)?d.delete(e):d.add(e),d})},[]),f=s.useCallback(()=>{const e=n=>n[Math.floor(Math.random()*n.length)];a({skinColor:e(R),hairColor:e(v),shirtColor:e(j),pantsColor:e(C),shoeColor:e(y)})},[]);return t.jsxs("div",{style:{fontFamily:"'SF Mono', monospace",background:"#0d1117",color:"#e6edf3",padding:24,minHeight:"100vh"},children:[t.jsx("h1",{style:{fontSize:18,color:"#58a6ff",marginBottom:4},children:"Sprite Blueprint Preview"}),t.jsx("p",{style:{fontSize:12,color:"#484f58",marginBottom:16},children:"All sprites rendered from declarative Blueprint data"}),t.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:12,padding:12,background:"#161b22",border:"1px solid #21262d",borderRadius:8,marginBottom:12,alignItems:"center"},children:[[["Skin","skinColor"],["Hair","hairColor"],["Shirt","shirtColor"],["Pants","pantsColor"],["Shoes","shoeColor"]].map(([e,n])=>t.jsxs("label",{style:{fontSize:11,color:"#8b949e",display:"flex",alignItems:"center",gap:4},children:[e,t.jsx("input",{type:"color",value:i[n],onChange:d=>a(b=>({...b,[n]:d.target.value})),style:{width:28,height:28,border:"1px solid #30363d",borderRadius:4,background:"none",cursor:"pointer"}})]},n)),t.jsx("button",{onClick:f,style:{background:"#21262d",color:"#e6edf3",border:"1px solid #30363d",borderRadius:4,padding:"4px 12px",fontSize:11,cursor:"pointer"},children:"Random"})]}),t.jsx("div",{style:{display:"flex",gap:8,marginBottom:16,flexWrap:"wrap"},children:g.map(e=>t.jsxs("label",{style:{fontSize:11,color:"#8b949e",display:"flex",alignItems:"center",gap:4,cursor:"pointer"},children:[t.jsx("input",{type:"checkbox",checked:r.has(e),onChange:()=>x(e)}),e]},e))}),t.jsxs("h2",{style:{fontSize:14,color:"#8b949e",margin:"24px 0 12px",borderBottom:"1px solid #21262d",paddingBottom:6},children:["Characters (",h.length,")"]}),t.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:24},children:h.map(e=>t.jsx(A,{id:e,ap:i,bobY:c,layers:r},e))}),t.jsxs("h2",{style:{fontSize:14,color:"#8b949e",margin:"24px 0 12px",borderBottom:"1px solid #21262d",paddingBottom:6},children:["Facilities (",u.length,")"]}),t.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:24},children:u.map(e=>t.jsx(F,{id:e},e))})]})}export{I as default};
|
package/src/web/dist/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Tycono</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-FesWAu2a.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BxDf0CSf.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
package/bin/init.ts
DELETED
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import readline from 'node:readline';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { detectAuth } from './auth-detect.js';
|
|
6
|
-
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
-
const __dirname = path.dirname(__filename);
|
|
9
|
-
const TEMPLATES_DIR = path.resolve(__dirname, '..', 'templates');
|
|
10
|
-
|
|
11
|
-
interface InitConfig {
|
|
12
|
-
companyName: string;
|
|
13
|
-
description: string;
|
|
14
|
-
apiKey: string;
|
|
15
|
-
team: 'startup' | 'research' | 'agency' | 'custom';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function ask(rl: readline.Interface, question: string, defaultValue?: string): Promise<string> {
|
|
19
|
-
const suffix = defaultValue ? ` (${defaultValue})` : '';
|
|
20
|
-
return new Promise((resolve) => {
|
|
21
|
-
rl.question(` ${question}${suffix}: `, (answer) => {
|
|
22
|
-
resolve(answer.trim() || defaultValue || '');
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function askSecret(rl: readline.Interface, question: string): Promise<string> {
|
|
28
|
-
return new Promise((resolve) => {
|
|
29
|
-
rl.question(` ${question}: `, (answer) => {
|
|
30
|
-
resolve(answer.trim());
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function askChoice(rl: readline.Interface, question: string, choices: string[]): Promise<string> {
|
|
36
|
-
return new Promise((resolve) => {
|
|
37
|
-
console.log(`\n ${question}`);
|
|
38
|
-
choices.forEach((c, i) => console.log(` ${i + 1}. ${c}`));
|
|
39
|
-
rl.question(' Choice: ', (answer) => {
|
|
40
|
-
const idx = parseInt(answer.trim(), 10) - 1;
|
|
41
|
-
if (idx >= 0 && idx < choices.length) {
|
|
42
|
-
resolve(choices[idx]);
|
|
43
|
-
} else {
|
|
44
|
-
resolve(choices[0]); // default to first
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function loadTemplate(name: string): string {
|
|
51
|
-
return fs.readFileSync(path.join(TEMPLATES_DIR, name), 'utf-8');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
interface TeamRole {
|
|
55
|
-
id: string;
|
|
56
|
-
name: string;
|
|
57
|
-
level: string;
|
|
58
|
-
reportsTo: string;
|
|
59
|
-
persona: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function loadTeam(teamName: string): TeamRole[] {
|
|
63
|
-
const teamPath = path.join(TEMPLATES_DIR, 'teams', `${teamName}.json`);
|
|
64
|
-
if (!fs.existsSync(teamPath)) return [];
|
|
65
|
-
return JSON.parse(fs.readFileSync(teamPath, 'utf-8'));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function renderTemplate(template: string, vars: Record<string, string>): string {
|
|
69
|
-
let result = template;
|
|
70
|
-
for (const [key, value] of Object.entries(vars)) {
|
|
71
|
-
result = result.replaceAll(`{{${key}}}`, value);
|
|
72
|
-
}
|
|
73
|
-
return result;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function scaffold(config: InitConfig): void {
|
|
77
|
-
const root = process.cwd();
|
|
78
|
-
const vars = {
|
|
79
|
-
COMPANY_NAME: config.companyName,
|
|
80
|
-
DESCRIPTION: config.description,
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
// Create directories
|
|
84
|
-
const dirs = [
|
|
85
|
-
'company',
|
|
86
|
-
'roles',
|
|
87
|
-
'projects',
|
|
88
|
-
'architecture',
|
|
89
|
-
'operations',
|
|
90
|
-
'operations/standup',
|
|
91
|
-
'operations/waves',
|
|
92
|
-
'operations/decisions',
|
|
93
|
-
'knowledge',
|
|
94
|
-
'.claude/skills',
|
|
95
|
-
];
|
|
96
|
-
for (const dir of dirs) {
|
|
97
|
-
fs.mkdirSync(path.join(root, dir), { recursive: true });
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Write CLAUDE.md
|
|
101
|
-
const claudeTmpl = loadTemplate('CLAUDE.md.tmpl');
|
|
102
|
-
fs.writeFileSync(path.join(root, 'CLAUDE.md'), renderTemplate(claudeTmpl, vars));
|
|
103
|
-
|
|
104
|
-
// Write company/company.md
|
|
105
|
-
const companyTmpl = loadTemplate('company.md.tmpl');
|
|
106
|
-
fs.writeFileSync(path.join(root, 'company', 'company.md'), renderTemplate(companyTmpl, vars));
|
|
107
|
-
|
|
108
|
-
// Write roles/roles.md
|
|
109
|
-
const rolesTmpl = loadTemplate('roles.md.tmpl');
|
|
110
|
-
fs.writeFileSync(path.join(root, 'roles', 'roles.md'), renderTemplate(rolesTmpl, vars));
|
|
111
|
-
|
|
112
|
-
// Write .gitignore
|
|
113
|
-
const giTmpl = loadTemplate('gitignore.tmpl');
|
|
114
|
-
const gitignorePath = path.join(root, '.gitignore');
|
|
115
|
-
if (!fs.existsSync(gitignorePath)) {
|
|
116
|
-
fs.writeFileSync(gitignorePath, giTmpl);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Write .env
|
|
120
|
-
const envPath = path.join(root, '.env');
|
|
121
|
-
if (config.apiKey) {
|
|
122
|
-
fs.writeFileSync(envPath, `ANTHROPIC_API_KEY=${config.apiKey}\n`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Create team roles
|
|
126
|
-
if (config.team !== 'custom') {
|
|
127
|
-
const roles = loadTeam(config.team);
|
|
128
|
-
for (const role of roles) {
|
|
129
|
-
const roleDir = path.join(root, 'roles', role.id);
|
|
130
|
-
const skillDir = path.join(root, '.claude', 'skills', role.id);
|
|
131
|
-
const journalDir = path.join(roleDir, 'journal');
|
|
132
|
-
|
|
133
|
-
fs.mkdirSync(roleDir, { recursive: true });
|
|
134
|
-
fs.mkdirSync(journalDir, { recursive: true });
|
|
135
|
-
fs.mkdirSync(skillDir, { recursive: true });
|
|
136
|
-
|
|
137
|
-
// role.yaml
|
|
138
|
-
const yaml = [
|
|
139
|
-
`id: ${role.id}`,
|
|
140
|
-
`name: "${role.name}"`,
|
|
141
|
-
`level: ${role.level}`,
|
|
142
|
-
`reports_to: ${role.reportsTo}`,
|
|
143
|
-
`persona: "${role.persona}"`,
|
|
144
|
-
'authority:',
|
|
145
|
-
' autonomous:',
|
|
146
|
-
' - Implementation within assigned scope',
|
|
147
|
-
' needs_approval:',
|
|
148
|
-
' - Architecture changes',
|
|
149
|
-
'knowledge:',
|
|
150
|
-
' reads:',
|
|
151
|
-
' - projects/',
|
|
152
|
-
' writes:',
|
|
153
|
-
' - projects/',
|
|
154
|
-
'reports:',
|
|
155
|
-
' daily: standup',
|
|
156
|
-
' weekly: summary',
|
|
157
|
-
].join('\n');
|
|
158
|
-
fs.writeFileSync(path.join(roleDir, 'role.yaml'), yaml + '\n');
|
|
159
|
-
|
|
160
|
-
// profile.md
|
|
161
|
-
const profile = `# ${role.name}\n\n> ${role.persona}\n\n| Item | Value |\n|------|-------|\n| ID | ${role.id} |\n| Level | ${role.level} |\n| Reports To | ${role.reportsTo} |\n`;
|
|
162
|
-
fs.writeFileSync(path.join(roleDir, 'profile.md'), profile);
|
|
163
|
-
|
|
164
|
-
// SKILL.md
|
|
165
|
-
const skill = `# ${role.name} Skills\n\nSkill definitions for the ${role.name} role.\n`;
|
|
166
|
-
fs.writeFileSync(path.join(skillDir, 'SKILL.md'), skill);
|
|
167
|
-
|
|
168
|
-
// Append to roles.md Hub table
|
|
169
|
-
const rolesHubPath = path.join(root, 'roles', 'roles.md');
|
|
170
|
-
if (fs.existsSync(rolesHubPath)) {
|
|
171
|
-
const hubContent = fs.readFileSync(rolesHubPath, 'utf-8');
|
|
172
|
-
const row = `| ${role.name} | ${role.id} | ${role.level} | ${role.reportsTo} | Active |`;
|
|
173
|
-
fs.writeFileSync(rolesHubPath, hubContent.trimEnd() + '\n' + row + '\n');
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Append to CLAUDE.md org table
|
|
177
|
-
const claudeMdPath = path.join(root, 'CLAUDE.md');
|
|
178
|
-
if (fs.existsSync(claudeMdPath)) {
|
|
179
|
-
const claudeContent = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
180
|
-
const orgRow = `| **${role.name}** | AI (${role.id}) | ${role.level} | ${role.reportsTo} | Active |`;
|
|
181
|
-
const orgMatch = claudeContent.match(/(## Organization[\s\S]*?\n(\|[^\n]*\n)+)/);
|
|
182
|
-
if (orgMatch) {
|
|
183
|
-
const insertPos = (orgMatch.index ?? 0) + orgMatch[0].length;
|
|
184
|
-
const updated = claudeContent.slice(0, insertPos) + orgRow + '\n' + claudeContent.slice(insertPos);
|
|
185
|
-
fs.writeFileSync(claudeMdPath, updated);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Hub files for empty directories
|
|
192
|
-
const hubs: Record<string, string> = {
|
|
193
|
-
'projects/projects.md': `# Projects\n\nProject listing for ${config.companyName}.\n\n| Project | Status | Lead |\n|---------|--------|------|\n`,
|
|
194
|
-
'architecture/architecture.md': `# Architecture\n\nTechnical architecture for ${config.companyName}.\n`,
|
|
195
|
-
'knowledge/knowledge.md': `# Knowledge Base\n\nDomain knowledge for ${config.companyName}.\n`,
|
|
196
|
-
};
|
|
197
|
-
for (const [filePath, content] of Object.entries(hubs)) {
|
|
198
|
-
const full = path.join(root, filePath);
|
|
199
|
-
if (!fs.existsSync(full)) {
|
|
200
|
-
fs.writeFileSync(full, content);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export async function runInit(args: string[] = []): Promise<void> {
|
|
206
|
-
const useDefaults = args.includes('-y') || args.includes('--yes');
|
|
207
|
-
// Parse --name "Company Name" from args
|
|
208
|
-
const nameIdx = args.indexOf('--name');
|
|
209
|
-
const cliName = nameIdx >= 0 && args[nameIdx + 1] ? args[nameIdx + 1] : '';
|
|
210
|
-
// Parse --template startup|research|agency|custom
|
|
211
|
-
const tmplIdx = args.indexOf('--template');
|
|
212
|
-
const cliTemplate = tmplIdx >= 0 && args[tmplIdx + 1] ? args[tmplIdx + 1] as InitConfig['team'] : '';
|
|
213
|
-
|
|
214
|
-
console.log(`
|
|
215
|
-
┌─────────────────────────────────────────┐
|
|
216
|
-
│ │
|
|
217
|
-
│ tycono init │
|
|
218
|
-
│ Create your AI company │
|
|
219
|
-
│ │
|
|
220
|
-
└─────────────────────────────────────────┘
|
|
221
|
-
`);
|
|
222
|
-
|
|
223
|
-
// Check if already initialized
|
|
224
|
-
if (fs.existsSync(path.join(process.cwd(), 'CLAUDE.md'))) {
|
|
225
|
-
if (!useDefaults) {
|
|
226
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
227
|
-
console.log(' A company already exists in this directory (CLAUDE.md found).');
|
|
228
|
-
const overwrite = await ask(rl, 'Overwrite? (y/N)', 'N');
|
|
229
|
-
rl.close();
|
|
230
|
-
if (overwrite.toLowerCase() !== 'y') {
|
|
231
|
-
console.log(' Aborted.');
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
let companyName = cliName || 'My Company';
|
|
238
|
-
let description = 'An AI-powered organization';
|
|
239
|
-
let apiKey = process.env.ANTHROPIC_API_KEY || '';
|
|
240
|
-
const validTeams = ['startup', 'research', 'agency', 'custom'] as const;
|
|
241
|
-
let team: InitConfig['team'] = (cliTemplate && validTeams.includes(cliTemplate as typeof validTeams[number]))
|
|
242
|
-
? cliTemplate as InitConfig['team']
|
|
243
|
-
: 'startup';
|
|
244
|
-
|
|
245
|
-
if (useDefaults) {
|
|
246
|
-
console.log(' Using defaults (-y flag)\n');
|
|
247
|
-
const auth = detectAuth();
|
|
248
|
-
console.log(` AI Engine: ${auth.message}\n`);
|
|
249
|
-
} else {
|
|
250
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
251
|
-
|
|
252
|
-
// Step 1: Company info
|
|
253
|
-
console.log(' Step 1/4: Company Info\n');
|
|
254
|
-
companyName = await ask(rl, 'Company name', 'My Company');
|
|
255
|
-
description = await ask(rl, 'Description', 'An AI-powered organization');
|
|
256
|
-
|
|
257
|
-
// Step 2: Auth detection
|
|
258
|
-
console.log('\n Step 2/4: AI Engine\n');
|
|
259
|
-
const auth = detectAuth();
|
|
260
|
-
if (auth.engine === 'claude-cli') {
|
|
261
|
-
console.log(` ✓ ${auth.message}`);
|
|
262
|
-
console.log(' Your AI roles will use Claude Code to execute tasks.\n');
|
|
263
|
-
} else if (auth.engine === 'direct-api') {
|
|
264
|
-
console.log(` ✓ ${auth.message}\n`);
|
|
265
|
-
} else {
|
|
266
|
-
console.log(' No Claude CLI or API key detected.\n');
|
|
267
|
-
console.log(' Option A: Install Claude Code → https://claude.ai/download');
|
|
268
|
-
console.log(' Option B: Enter an Anthropic API key\n');
|
|
269
|
-
apiKey = await askSecret(rl, 'ANTHROPIC_API_KEY (press Enter to skip)');
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Step 3: Team template
|
|
273
|
-
console.log('\n Step 3/4: Team Template\n');
|
|
274
|
-
const teamChoice = await askChoice(rl, 'Select a team template:', [
|
|
275
|
-
'Startup (CTO + PM + Engineer)',
|
|
276
|
-
'Research (Lead Researcher + Analyst + Writer)',
|
|
277
|
-
'Agency (Creative Director + Designer + Developer)',
|
|
278
|
-
'Custom (no pre-built roles)',
|
|
279
|
-
]);
|
|
280
|
-
|
|
281
|
-
const teamMap: Record<string, InitConfig['team']> = {
|
|
282
|
-
'Startup (CTO + PM + Engineer)': 'startup',
|
|
283
|
-
'Research (Lead Researcher + Analyst + Writer)': 'research',
|
|
284
|
-
'Agency (Creative Director + Designer + Developer)': 'agency',
|
|
285
|
-
'Custom (no pre-built roles)': 'custom',
|
|
286
|
-
};
|
|
287
|
-
team = teamMap[teamChoice] ?? 'startup';
|
|
288
|
-
|
|
289
|
-
rl.close();
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Scaffold
|
|
293
|
-
console.log(' Step 4/4: Scaffolding\n');
|
|
294
|
-
console.log(` Company: ${companyName}`);
|
|
295
|
-
console.log(` Template: ${team}`);
|
|
296
|
-
console.log(` API Key: ${apiKey ? 'configured' : 'skipped'}`);
|
|
297
|
-
console.log('');
|
|
298
|
-
|
|
299
|
-
scaffold({ companyName, description, apiKey, team });
|
|
300
|
-
|
|
301
|
-
console.log(' Done! Your AI company is ready.\n');
|
|
302
|
-
console.log(' Next steps:');
|
|
303
|
-
console.log(' 1. cd into this directory');
|
|
304
|
-
console.log(' 2. Run: npx tycono');
|
|
305
|
-
console.log(' 3. Open the dashboard in your browser\n');
|
|
306
|
-
}
|