telos-framework 0.1.3 → 0.2.0
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/lib/commands/init-state.js +102 -0
- package/lib/commands/init.js +143 -68
- package/package.json +1 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const STATE_FILE = '.telos-init-state.json';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Get the state file path for the current directory
|
|
8
|
+
*/
|
|
9
|
+
function getStateFilePath(cwd = process.cwd()) {
|
|
10
|
+
return path.join(cwd, STATE_FILE);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Load existing initialization state if present
|
|
15
|
+
*/
|
|
16
|
+
function loadState(cwd = process.cwd()) {
|
|
17
|
+
const statePath = getStateFilePath(cwd);
|
|
18
|
+
|
|
19
|
+
if (!fs.existsSync(statePath)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const content = fs.readFileSync(statePath, 'utf8');
|
|
25
|
+
return JSON.parse(content);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Save initialization state
|
|
33
|
+
*/
|
|
34
|
+
function saveState(state, cwd = process.cwd()) {
|
|
35
|
+
const statePath = getStateFilePath(cwd);
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
fs.writeFileSync(statePath, JSON.stringify(state, null, 2), 'utf8');
|
|
39
|
+
return true;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Update specific phase data in state
|
|
47
|
+
*/
|
|
48
|
+
function updatePhase(phase, data, cwd = process.cwd()) {
|
|
49
|
+
const currentState = loadState(cwd) || { phases: {}, timestamp: new Date().toISOString() };
|
|
50
|
+
|
|
51
|
+
currentState.phases[phase] = {
|
|
52
|
+
...data,
|
|
53
|
+
completedAt: new Date().toISOString()
|
|
54
|
+
};
|
|
55
|
+
currentState.lastPhase = phase;
|
|
56
|
+
currentState.lastUpdated = new Date().toISOString();
|
|
57
|
+
|
|
58
|
+
return saveState(currentState, cwd);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Clear initialization state (call on successful completion)
|
|
63
|
+
*/
|
|
64
|
+
function clearState(cwd = process.cwd()) {
|
|
65
|
+
const statePath = getStateFilePath(cwd);
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
if (fs.existsSync(statePath)) {
|
|
69
|
+
fs.unlinkSync(statePath);
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check if a specific phase is completed
|
|
79
|
+
*/
|
|
80
|
+
function isPhaseComplete(state, phase) {
|
|
81
|
+
return !!(state && state.phases && state.phases[phase]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get phase data if it exists
|
|
86
|
+
*/
|
|
87
|
+
function getPhaseData(state, phase) {
|
|
88
|
+
if (state && state.phases && state.phases[phase]) {
|
|
89
|
+
return state.phases[phase].data;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
loadState,
|
|
96
|
+
saveState,
|
|
97
|
+
updatePhase,
|
|
98
|
+
clearState,
|
|
99
|
+
isPhaseComplete,
|
|
100
|
+
getPhaseData,
|
|
101
|
+
getStateFilePath
|
|
102
|
+
};
|
package/lib/commands/init.js
CHANGED
|
@@ -14,89 +14,163 @@ const { generateLogosMd } = require('../generators/logos-md-generator');
|
|
|
14
14
|
const { consolidateAgents } = require('../generators/agents-md-generator');
|
|
15
15
|
const { detectPlatforms, getPlatformConfig } = require('../platform/platform-detector');
|
|
16
16
|
const { createSymlinks } = require('../platform/symlink-creator');
|
|
17
|
+
const { loadState, updatePhase, clearState, isPhaseComplete, getPhaseData } = require('./init-state');
|
|
17
18
|
|
|
18
19
|
async function initCommand(options) {
|
|
19
|
-
console.log(chalk.bold.cyan('\n
|
|
20
|
+
console.log(chalk.bold.cyan('\n╔══════════════════════════════════════════╗'));
|
|
20
21
|
console.log(chalk.bold.cyan('║ Telos Multi-Agent Initialization ║'));
|
|
21
|
-
console.log(chalk.bold.cyan('
|
|
22
|
+
console.log(chalk.bold.cyan('╚══════════════════════════════════════════╝\n'));
|
|
22
23
|
|
|
23
24
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
spinner.start('Generating TELOS.md...');
|
|
31
|
-
const telosPath = path.join(process.cwd(), 'telos', 'content', 'TELOS.md');
|
|
32
|
-
await generateTelosMd(hierarchy, telosPath);
|
|
33
|
-
spinner.succeed(`Generated ${telosPath}`);
|
|
34
|
-
|
|
35
|
-
spinner.start('Generating L9 Telos-Guardian agent...');
|
|
36
|
-
const l9AgentPath = path.join(process.cwd(), 'telos', 'agents', 'l9-telos-guardian.md');
|
|
37
|
-
await generateL9Agent(hierarchy, l9AgentPath);
|
|
38
|
-
spinner.succeed(`Generated ${l9AgentPath}`);
|
|
39
|
-
|
|
40
|
-
console.log(chalk.green('\n✓ Phase 1: Telos Discovery Complete\n'));
|
|
41
|
-
|
|
42
|
-
spinner.start('Scanning project for tools and frameworks...');
|
|
43
|
-
const projectScan = await scanProject(process.cwd());
|
|
44
|
-
spinner.succeed('Project scan complete');
|
|
45
|
-
|
|
46
|
-
spinner.start('Discovering MCP servers...');
|
|
47
|
-
const mcpServers = await discoverMcpServers();
|
|
48
|
-
const mcpCapabilities = mapMcpToCapabilities(mcpServers);
|
|
49
|
-
spinner.succeed(`Found ${mcpServers.length} MCP server(s)`);
|
|
50
|
-
|
|
51
|
-
spinner.start('Mapping tools to agent levels...');
|
|
52
|
-
const levelTools = mapToolsToLevels(projectScan, mcpCapabilities);
|
|
53
|
-
const recommendations = getToolRecommendations(levelTools);
|
|
54
|
-
spinner.succeed('Tool mapping complete');
|
|
55
|
-
|
|
56
|
-
spinner.start('Generating TOOLS.md...');
|
|
57
|
-
const toolsPath = path.join(process.cwd(), 'telos', 'content', 'TOOLS.md');
|
|
58
|
-
await generateToolsMd(levelTools, projectScan, mcpServers, recommendations, toolsPath);
|
|
59
|
-
spinner.succeed(`Generated ${toolsPath}`);
|
|
60
|
-
|
|
61
|
-
console.log(chalk.green('\n✓ Phase 2: Tool Discovery Complete\n'));
|
|
25
|
+
// Load previous state if exists
|
|
26
|
+
const savedState = loadState();
|
|
27
|
+
if (savedState) {
|
|
28
|
+
console.log(chalk.yellow('⚠ Found previous initialization attempt from ' + new Date(savedState.timestamp).toLocaleString()));
|
|
29
|
+
console.log(chalk.yellow(' Resuming from last successful phase...\n'));
|
|
30
|
+
}
|
|
62
31
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
32
|
+
// Phase 0: Telos Discovery
|
|
33
|
+
let telosData;
|
|
34
|
+
if (isPhaseComplete(savedState, 'telosDiscovery')) {
|
|
35
|
+
console.log(chalk.dim('↻ Using saved Telos data'));
|
|
36
|
+
telosData = getPhaseData(savedState, 'telosDiscovery');
|
|
37
|
+
} else {
|
|
38
|
+
telosData = await discoverTelos(options);
|
|
39
|
+
updatePhase('telosDiscovery', { data: telosData });
|
|
40
|
+
}
|
|
69
41
|
|
|
70
|
-
|
|
42
|
+
// Phase 0.5: Hierarchy Building
|
|
43
|
+
let hierarchy;
|
|
44
|
+
if (isPhaseComplete(savedState, 'hierarchyBuilding')) {
|
|
45
|
+
console.log(chalk.dim('↻ Using saved hierarchy'));
|
|
46
|
+
hierarchy = getPhaseData(savedState, 'hierarchyBuilding');
|
|
47
|
+
} else {
|
|
48
|
+
if (options.quick) {
|
|
49
|
+
const spinner = ora('Building purpose hierarchy...').start();
|
|
50
|
+
hierarchy = await buildHierarchy(telosData, options);
|
|
51
|
+
spinner.succeed('Purpose hierarchy built');
|
|
52
|
+
} else {
|
|
53
|
+
hierarchy = await buildHierarchy(telosData, options);
|
|
54
|
+
console.log(chalk.green('\n✓ Purpose hierarchy built\n'));
|
|
55
|
+
}
|
|
56
|
+
updatePhase('hierarchyBuilding', { data: hierarchy });
|
|
57
|
+
}
|
|
71
58
|
|
|
72
|
-
|
|
59
|
+
// Phase 1: Generate TELOS.md and L9 Agent
|
|
60
|
+
if (!isPhaseComplete(savedState, 'phase1')) {
|
|
61
|
+
const spinner = ora('Generating TELOS.md...').start();
|
|
62
|
+
const telosPath = path.join(process.cwd(), 'telos', 'content', 'TELOS.md');
|
|
63
|
+
await generateTelosMd(hierarchy, telosPath);
|
|
64
|
+
spinner.succeed(`Generated ${telosPath}`);
|
|
65
|
+
|
|
66
|
+
spinner.start('Generating L9 Telos-Guardian agent...');
|
|
67
|
+
const l9AgentPath = path.join(process.cwd(), 'telos', 'agents', 'l9-telos-guardian.md');
|
|
68
|
+
await generateL9Agent(hierarchy, l9AgentPath);
|
|
69
|
+
spinner.succeed(`Generated ${l9AgentPath}`);
|
|
70
|
+
|
|
71
|
+
updatePhase('phase1', { completed: true });
|
|
72
|
+
console.log(chalk.green('\n✓ Phase 1: Telos Discovery Complete\n'));
|
|
73
|
+
} else {
|
|
74
|
+
console.log(chalk.dim('✓ Phase 1: Already completed\n'));
|
|
75
|
+
}
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
// Phase 2: Tool Discovery
|
|
78
|
+
let projectScan, mcpServers, mcpCapabilities, levelTools, recommendations;
|
|
79
|
+
if (isPhaseComplete(savedState, 'phase2')) {
|
|
80
|
+
console.log(chalk.dim('↻ Using saved tool discovery data'));
|
|
81
|
+
const phase2Data = getPhaseData(savedState, 'phase2');
|
|
82
|
+
projectScan = phase2Data.projectScan;
|
|
83
|
+
mcpServers = phase2Data.mcpServers;
|
|
84
|
+
mcpCapabilities = phase2Data.mcpCapabilities;
|
|
85
|
+
levelTools = phase2Data.levelTools;
|
|
86
|
+
recommendations = phase2Data.recommendations;
|
|
87
|
+
console.log(chalk.dim('✓ Phase 2: Already completed\n'));
|
|
88
|
+
} else {
|
|
89
|
+
const spinner = ora('Scanning project for tools and frameworks...').start();
|
|
90
|
+
projectScan = await scanProject(process.cwd());
|
|
91
|
+
spinner.succeed('Project scan complete');
|
|
92
|
+
|
|
93
|
+
spinner.start('Discovering MCP servers...');
|
|
94
|
+
mcpServers = await discoverMcpServers();
|
|
95
|
+
mcpCapabilities = mapMcpToCapabilities(mcpServers);
|
|
96
|
+
spinner.succeed(`Found ${mcpServers.length} MCP server(s)`);
|
|
97
|
+
|
|
98
|
+
spinner.start('Mapping tools to agent levels...');
|
|
99
|
+
levelTools = mapToolsToLevels(projectScan, mcpCapabilities);
|
|
100
|
+
recommendations = getToolRecommendations(levelTools);
|
|
101
|
+
spinner.succeed('Tool mapping complete');
|
|
102
|
+
|
|
103
|
+
spinner.start('Generating TOOLS.md...');
|
|
104
|
+
const toolsPath = path.join(process.cwd(), 'telos', 'content', 'TOOLS.md');
|
|
105
|
+
await generateToolsMd(levelTools, projectScan, mcpServers, recommendations, toolsPath);
|
|
106
|
+
spinner.succeed(`Generated ${toolsPath}`);
|
|
107
|
+
|
|
108
|
+
updatePhase('phase2', {
|
|
109
|
+
completed: true,
|
|
110
|
+
data: { projectScan, mcpServers, mcpCapabilities, levelTools, recommendations }
|
|
111
|
+
});
|
|
112
|
+
console.log(chalk.green('\n✓ Phase 2: Tool Discovery Complete\n'));
|
|
113
|
+
}
|
|
78
114
|
|
|
79
|
-
|
|
115
|
+
// Phase 3: Agent Generation
|
|
116
|
+
if (!isPhaseComplete(savedState, 'phase3')) {
|
|
117
|
+
const spinner = ora('Generating all agent definitions...').start();
|
|
118
|
+
const agentsDir = path.join(process.cwd(), 'telos', 'agents');
|
|
119
|
+
|
|
120
|
+
await generateL1Agent(hierarchy, levelTools.L1.tools, path.join(agentsDir, 'l1-syntax-linter.md'));
|
|
121
|
+
await generateL2Agent(hierarchy, levelTools.L2.tools, path.join(agentsDir, 'l2-function-author.md'));
|
|
122
|
+
await generateAllAgents(hierarchy, levelTools, agentsDir);
|
|
123
|
+
|
|
124
|
+
spinner.succeed('Generated all 9 agent definitions');
|
|
125
|
+
|
|
126
|
+
updatePhase('phase3', { completed: true });
|
|
127
|
+
console.log(chalk.green('\n✓ Phase 3: Agent Generation Complete\n'));
|
|
128
|
+
} else {
|
|
129
|
+
console.log(chalk.dim('✓ Phase 3: Already completed\n'));
|
|
130
|
+
}
|
|
80
131
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
132
|
+
// Phase 4: Logos Generation
|
|
133
|
+
if (!isPhaseComplete(savedState, 'phase4')) {
|
|
134
|
+
const spinner = ora('Generating Logos orchestrator documentation...').start();
|
|
135
|
+
const logosPath = path.join(process.cwd(), 'telos', 'content', 'LOGOS.md');
|
|
136
|
+
await generateLogosMd(logosPath);
|
|
137
|
+
spinner.succeed(`Generated ${logosPath}`);
|
|
138
|
+
|
|
139
|
+
updatePhase('phase4', { completed: true });
|
|
140
|
+
console.log(chalk.green('\n✓ Phase 4: Logos Orchestrator Complete\n'));
|
|
141
|
+
} else {
|
|
142
|
+
console.log(chalk.dim('✓ Phase 4: Already completed\n'));
|
|
143
|
+
}
|
|
85
144
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
145
|
+
// Phase 5: Consolidation and Symlinks
|
|
146
|
+
if (!isPhaseComplete(savedState, 'phase5')) {
|
|
147
|
+
const spinner = ora('Consolidating agents into AGENTS.md...').start();
|
|
148
|
+
const agentsMdPath = path.join(process.cwd(), 'telos', 'content', 'AGENTS.md');
|
|
149
|
+
await consolidateAgents(path.join(process.cwd(), 'telos', 'agents'), agentsMdPath);
|
|
150
|
+
spinner.succeed(`Generated ${agentsMdPath}`);
|
|
151
|
+
|
|
152
|
+
spinner.start('Detecting platforms and creating symlinks...');
|
|
153
|
+
const platforms = await detectPlatforms(process.cwd());
|
|
154
|
+
let symlinkCount = 0;
|
|
155
|
+
|
|
156
|
+
for (const platform of platforms) {
|
|
157
|
+
const config = getPlatformConfig(platform.name);
|
|
158
|
+
const results = await createSymlinks(process.cwd(), config);
|
|
159
|
+
symlinkCount += results.filter(r => r.success).length;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
spinner.succeed(`Created ${symlinkCount} platform symlink(s) for ${platforms.map(p => p.name).join(', ')}`);
|
|
163
|
+
|
|
164
|
+
updatePhase('phase5', { completed: true });
|
|
165
|
+
console.log(chalk.green('\n✓ Phase 5: Platform Configuration Complete\n'));
|
|
166
|
+
} else {
|
|
167
|
+
console.log(chalk.dim('✓ Phase 5: Already completed\n'));
|
|
94
168
|
}
|
|
95
169
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
console.log(chalk.green('\n✓ Phase 5: Platform Configuration Complete\n'));
|
|
170
|
+
// Clear state on successful completion
|
|
171
|
+
clearState();
|
|
99
172
|
|
|
173
|
+
const telosPath = path.join(process.cwd(), 'telos', 'content', 'TELOS.md');
|
|
100
174
|
console.log(chalk.cyan('Your Telos has been captured in:'));
|
|
101
175
|
console.log(chalk.bold(` ${telosPath}\n`));
|
|
102
176
|
|
|
@@ -105,6 +179,7 @@ async function initCommand(options) {
|
|
|
105
179
|
if (options.verbose) {
|
|
106
180
|
console.error(error);
|
|
107
181
|
}
|
|
182
|
+
console.log(chalk.yellow('\n💾 Progress has been saved. Run `telos init` again to resume.\n'));
|
|
108
183
|
process.exit(1);
|
|
109
184
|
}
|
|
110
185
|
}
|
package/package.json
CHANGED