telos-framework 0.1.4 → 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 +138 -70
- 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,96 +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
|
+
// 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
|
+
}
|
|
31
|
+
|
|
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
|
+
}
|
|
25
41
|
|
|
42
|
+
// Phase 0.5: Hierarchy Building
|
|
26
43
|
let hierarchy;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
hierarchy = await buildHierarchy(telosData, options);
|
|
31
|
-
spinner.succeed('Purpose hierarchy built');
|
|
44
|
+
if (isPhaseComplete(savedState, 'hierarchyBuilding')) {
|
|
45
|
+
console.log(chalk.dim('↻ Using saved hierarchy'));
|
|
46
|
+
hierarchy = getPhaseData(savedState, 'hierarchyBuilding');
|
|
32
47
|
} else {
|
|
33
|
-
|
|
34
|
-
|
|
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 });
|
|
35
57
|
}
|
|
36
58
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const l9AgentPath = path.join(process.cwd(), 'telos', 'agents', 'l9-telos-guardian.md');
|
|
44
|
-
await generateL9Agent(hierarchy, l9AgentPath);
|
|
45
|
-
spinner.succeed(`Generated ${l9AgentPath}`);
|
|
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}`);
|
|
46
65
|
|
|
47
|
-
|
|
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}`);
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const mcpServers = await discoverMcpServers();
|
|
55
|
-
const mcpCapabilities = mapMcpToCapabilities(mcpServers);
|
|
56
|
-
spinner.succeed(`Found ${mcpServers.length} MCP server(s)`);
|
|
57
|
-
|
|
58
|
-
spinner.start('Mapping tools to agent levels...');
|
|
59
|
-
const levelTools = mapToolsToLevels(projectScan, mcpCapabilities);
|
|
60
|
-
const recommendations = getToolRecommendations(levelTools);
|
|
61
|
-
spinner.succeed('Tool mapping complete');
|
|
62
|
-
|
|
63
|
-
spinner.start('Generating TOOLS.md...');
|
|
64
|
-
const toolsPath = path.join(process.cwd(), 'telos', 'content', 'TOOLS.md');
|
|
65
|
-
await generateToolsMd(levelTools, projectScan, mcpServers, recommendations, toolsPath);
|
|
66
|
-
spinner.succeed(`Generated ${toolsPath}`);
|
|
67
|
-
|
|
68
|
-
console.log(chalk.green('\n✓ Phase 2: Tool Discovery Complete\n'));
|
|
69
|
-
|
|
70
|
-
spinner.start('Generating all agent definitions...');
|
|
71
|
-
const agentsDir = path.join(process.cwd(), 'telos', 'agents');
|
|
72
|
-
|
|
73
|
-
await generateL1Agent(hierarchy, levelTools.L1.tools, path.join(agentsDir, 'l1-syntax-linter.md'));
|
|
74
|
-
await generateL2Agent(hierarchy, levelTools.L2.tools, path.join(agentsDir, 'l2-function-author.md'));
|
|
75
|
-
await generateAllAgents(hierarchy, levelTools, agentsDir);
|
|
76
|
-
|
|
77
|
-
spinner.succeed('Generated all 9 agent definitions');
|
|
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
|
+
}
|
|
78
76
|
|
|
79
|
-
|
|
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
|
+
}
|
|
80
114
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
+
}
|
|
85
131
|
|
|
86
|
-
|
|
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}`);
|
|
87
138
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
+
}
|
|
92
144
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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'));
|
|
101
168
|
}
|
|
102
169
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
console.log(chalk.green('\n✓ Phase 5: Platform Configuration Complete\n'));
|
|
170
|
+
// Clear state on successful completion
|
|
171
|
+
clearState();
|
|
106
172
|
|
|
173
|
+
const telosPath = path.join(process.cwd(), 'telos', 'content', 'TELOS.md');
|
|
107
174
|
console.log(chalk.cyan('Your Telos has been captured in:'));
|
|
108
175
|
console.log(chalk.bold(` ${telosPath}\n`));
|
|
109
176
|
|
|
@@ -112,6 +179,7 @@ async function initCommand(options) {
|
|
|
112
179
|
if (options.verbose) {
|
|
113
180
|
console.error(error);
|
|
114
181
|
}
|
|
182
|
+
console.log(chalk.yellow('\n💾 Progress has been saved. Run `telos init` again to resume.\n'));
|
|
115
183
|
process.exit(1);
|
|
116
184
|
}
|
|
117
185
|
}
|
package/package.json
CHANGED