@specverse/engines 4.3.5 → 5.0.1
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/assets/examples/10-api/README.md +3 -3
- package/assets/prompts/core/README.md +1 -1
- package/dist/inference/core/rule-engine.d.ts +0 -12
- package/dist/inference/core/rule-engine.d.ts.map +1 -1
- package/dist/inference/core/rule-engine.js +99 -968
- package/dist/inference/core/rule-engine.js.map +1 -1
- package/dist/inference/core/template-helpers.d.ts +56 -0
- package/dist/inference/core/template-helpers.d.ts.map +1 -0
- package/dist/inference/core/template-helpers.js +87 -0
- package/dist/inference/core/template-helpers.js.map +1 -0
- package/dist/inference/logical/generators/service-generator.d.ts.map +1 -1
- package/dist/inference/logical/generators/service-generator.js +0 -4
- package/dist/inference/logical/generators/service-generator.js.map +1 -1
- package/dist/inference/ui-contracts/rules/lifecycle-state-visible-in-detail.d.ts +9 -7
- package/dist/inference/ui-contracts/rules/lifecycle-state-visible-in-detail.d.ts.map +1 -1
- package/dist/inference/ui-contracts/rules/lifecycle-state-visible-in-detail.js +27 -9
- package/dist/inference/ui-contracts/rules/lifecycle-state-visible-in-detail.js.map +1 -1
- package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +27 -5
- package/dist/libs/instance-factories/tools/README.md +1 -1
- package/dist/libs/instance-factories/tools/mcp.yaml +1 -1
- package/dist/libs/instance-factories/tools/templates/mcp/mcp-server-generator.js +342 -116
- package/dist/libs/instance-factories/tools/templates/vscode/vscode-extension-generator.js +172 -8
- package/dist/libs/instance-factories/tools/vscode.yaml +1 -1
- package/libs/instance-factories/cli/templates/commander/command-generator.ts +27 -5
- package/libs/instance-factories/tools/README.md +1 -1
- package/libs/instance-factories/tools/mcp.yaml +1 -1
- package/libs/instance-factories/tools/templates/mcp/mcp-server-generator.ts +392 -141
- package/libs/instance-factories/tools/templates/vscode/static/extension.ts +9 -2
- package/libs/instance-factories/tools/templates/vscode/vscode-extension-generator.ts +246 -10
- package/libs/instance-factories/tools/vscode.yaml +1 -1
- package/package.json +5 -4
- package/libs/instance-factories/tools/templates/mcp/static/docs/DEPLOYMENT_GUIDE.md +0 -630
- package/libs/instance-factories/tools/templates/mcp/static/docs/HYBRID_RESOURCE_SYSTEM.md +0 -330
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/EXTENSION_DEPLOYMENT.md +0 -552
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/LOCAL_DEPLOYMENT.md +0 -164
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/WEB_DEPLOYMENT.md +0 -247
- package/libs/instance-factories/tools/templates/mcp/static/package.json +0 -94
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-enterprise.js +0 -284
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-extension.js +0 -139
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-local.js +0 -74
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-web.js +0 -156
- package/libs/instance-factories/tools/templates/mcp/static/scripts/copy-canonical-files.js +0 -41
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-deployments.js +0 -259
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-hybrid-resources.js +0 -231
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-hybrid-simple.js +0 -196
- package/libs/instance-factories/tools/templates/mcp/static/src/controllers/MCPServerController.ts +0 -293
- package/libs/instance-factories/tools/templates/mcp/static/src/events/EventEmitter.ts +0 -90
- package/libs/instance-factories/tools/templates/mcp/static/src/index.ts +0 -24
- package/libs/instance-factories/tools/templates/mcp/static/src/interfaces/ResourceProvider.ts +0 -15
- package/libs/instance-factories/tools/templates/mcp/static/src/models/LibrarySuggestion.ts +0 -106
- package/libs/instance-factories/tools/templates/mcp/static/src/models/SpecVerseResource.ts +0 -75
- package/libs/instance-factories/tools/templates/mcp/static/src/server/mcp-server.ts +0 -239
- package/libs/instance-factories/tools/templates/mcp/static/src/services/CLIProxyService.ts +0 -1501
- package/libs/instance-factories/tools/templates/mcp/static/src/services/EmbeddedResourcesAdapter.ts +0 -211
- package/libs/instance-factories/tools/templates/mcp/static/src/services/EntityModuleService.ts +0 -308
- package/libs/instance-factories/tools/templates/mcp/static/src/services/HybridResourcesProvider.ts +0 -210
- package/libs/instance-factories/tools/templates/mcp/static/src/services/LibraryToolsService.ts +0 -356
- package/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorBridge.ts +0 -522
- package/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorToolsService.ts +0 -530
- package/libs/instance-factories/tools/templates/mcp/static/src/services/PromptToolsService.ts +0 -594
- package/libs/instance-factories/tools/templates/mcp/static/src/services/ResourcesProviderService.ts +0 -170
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/CLIProxyService.init.test.ts +0 -544
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/CLIProxyService.test.ts +0 -189
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/ResourcesProviderService.test.ts +0 -89
- package/libs/instance-factories/tools/templates/mcp/static/src/types/index.ts +0 -110
- package/libs/instance-factories/tools/templates/mcp/static/tsconfig.json +0 -28
- package/libs/instance-factories/tools/templates/vscode/static/schemas/specverse-v3-schema.json +0 -4279
- /package/libs/instance-factories/tools/templates/vscode/static/themes/{specverse-complete-theme.json → specverse-dark-theme.json} +0 -0
package/libs/instance-factories/tools/templates/mcp/static/src/services/HybridResourcesProvider.ts
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HybridResourcesProvider
|
|
3
|
-
* Unified resources provider that can use file system or embedded resources
|
|
4
|
-
* based on deployment environment
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { existsSync, readFileSync } from 'fs';
|
|
8
|
-
import { join, dirname } from 'path';
|
|
9
|
-
import { fileURLToPath } from 'url';
|
|
10
|
-
import { ResourcesProviderService } from './ResourcesProviderService.js';
|
|
11
|
-
import { EmbeddedResourcesAdapter, type EmbeddedResourcesMap } from './EmbeddedResourcesAdapter.js';
|
|
12
|
-
import type { ResourceProvider } from '../interfaces/ResourceProvider.js';
|
|
13
|
-
import type { SpecVerseResource, MCPToolResult } from '../types/index.js';
|
|
14
|
-
|
|
15
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
-
const __dirname = dirname(__filename);
|
|
17
|
-
|
|
18
|
-
export interface HybridConfig {
|
|
19
|
-
mode: 'auto' | 'filesystem' | 'embedded';
|
|
20
|
-
resourcesPath?: string;
|
|
21
|
-
embeddedResources?: EmbeddedResourcesMap;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export class HybridResourcesProvider implements ResourceProvider {
|
|
25
|
-
private provider: ResourcesProviderService | EmbeddedResourcesAdapter;
|
|
26
|
-
private mode: 'filesystem' | 'embedded';
|
|
27
|
-
|
|
28
|
-
constructor(config: HybridConfig) {
|
|
29
|
-
this.mode = this.detectMode(config);
|
|
30
|
-
|
|
31
|
-
if (this.mode === 'embedded') {
|
|
32
|
-
if (!config.embeddedResources) {
|
|
33
|
-
// For now, create a simple embedded adapter - we'll load resources asynchronously
|
|
34
|
-
this.provider = new EmbeddedResourcesAdapter({});
|
|
35
|
-
} else {
|
|
36
|
-
this.provider = new EmbeddedResourcesAdapter(config.embeddedResources);
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
this.provider = new ResourcesProviderService(config.resourcesPath);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private detectMode(config: HybridConfig): 'filesystem' | 'embedded' {
|
|
44
|
-
if (config.mode === 'filesystem') return 'filesystem';
|
|
45
|
-
if (config.mode === 'embedded') return 'embedded';
|
|
46
|
-
|
|
47
|
-
// Auto-detection for 'auto' mode
|
|
48
|
-
// Priority 1: Check if embedded resources are explicitly provided
|
|
49
|
-
if (config.embeddedResources) {
|
|
50
|
-
return 'embedded';
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Priority 2: Check if embedded-resources.js exists (web build indicator)
|
|
54
|
-
if (this.hasEmbeddedResourcesFile()) {
|
|
55
|
-
return 'embedded';
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Priority 3: Check if we're in a web deployment environment
|
|
59
|
-
if (this.isWebEnvironment()) {
|
|
60
|
-
return 'embedded';
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Priority 4: Check if resources directory exists for local/development
|
|
64
|
-
const resourcesPath = config.resourcesPath || join(__dirname, '../../resources');
|
|
65
|
-
if (existsSync(resourcesPath)) {
|
|
66
|
-
return 'filesystem';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Priority 5: Try to dynamically import embedded resources
|
|
70
|
-
if (this.tryImportEmbeddedResources()) {
|
|
71
|
-
return 'embedded';
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Default to filesystem for development environments
|
|
75
|
-
return 'filesystem';
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private hasEmbeddedResourcesFile(): boolean {
|
|
79
|
-
try {
|
|
80
|
-
// Check if embedded-resources.js exists in the same directory as the built files
|
|
81
|
-
const embeddedPath = join(dirname(__dirname), 'embedded-resources.js');
|
|
82
|
-
return existsSync(embeddedPath);
|
|
83
|
-
} catch {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private isWebEnvironment(): boolean {
|
|
89
|
-
// Detection heuristics for web environment
|
|
90
|
-
try {
|
|
91
|
-
// Check if we're in a browser-like environment
|
|
92
|
-
if (typeof window !== 'undefined') return true;
|
|
93
|
-
|
|
94
|
-
// Check if we have embedded resources file (web build indicator)
|
|
95
|
-
return this.hasEmbeddedResourcesFile();
|
|
96
|
-
} catch {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
private loadEmbeddedResources(): EmbeddedResourcesMap | null {
|
|
102
|
-
try {
|
|
103
|
-
// Try to load embedded resources from the web build
|
|
104
|
-
const embeddedPath = join(dirname(__dirname), 'embedded-resources.js');
|
|
105
|
-
if (existsSync(embeddedPath)) {
|
|
106
|
-
const content = readFileSync(embeddedPath, 'utf-8');
|
|
107
|
-
|
|
108
|
-
// Extract the EMBEDDED_RESOURCES object from the file
|
|
109
|
-
// This is a bit hacky but works for the generated embedded-resources.js
|
|
110
|
-
const match = content.match(/export const EMBEDDED_RESOURCES = ({[\s\S]*?});/);
|
|
111
|
-
if (match) {
|
|
112
|
-
// Use eval to parse the object (safe since we generated this file)
|
|
113
|
-
const embeddedResources = eval('(' + match[1] + ')');
|
|
114
|
-
return embeddedResources;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return null;
|
|
118
|
-
} catch (error) {
|
|
119
|
-
console.warn('Failed to load embedded resources:', error);
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
private async loadEmbeddedResourcesAsync(): Promise<EmbeddedResourcesMap | null> {
|
|
125
|
-
try {
|
|
126
|
-
// Try dynamic import of embedded resources
|
|
127
|
-
const embeddedPath = join(dirname(__dirname), 'embedded-resources.js');
|
|
128
|
-
if (existsSync(embeddedPath)) {
|
|
129
|
-
const embeddedModule = await import(embeddedPath);
|
|
130
|
-
return embeddedModule.EMBEDDED_RESOURCES || null;
|
|
131
|
-
}
|
|
132
|
-
return null;
|
|
133
|
-
} catch (error) {
|
|
134
|
-
console.warn('Dynamic import of embedded resources failed:', error);
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private tryImportEmbeddedResources(): any {
|
|
140
|
-
// This is for future async import support
|
|
141
|
-
return this.loadEmbeddedResources();
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async initializeResources(): Promise<void> {
|
|
145
|
-
// If we're in embedded mode but don't have resources loaded yet, try to load them
|
|
146
|
-
if (this.mode === 'embedded' && this.provider instanceof EmbeddedResourcesAdapter) {
|
|
147
|
-
const providerInfo = this.provider.getEmbeddedResourcesInfo();
|
|
148
|
-
if (providerInfo.count === 0) {
|
|
149
|
-
// Try to load embedded resources dynamically
|
|
150
|
-
try {
|
|
151
|
-
const embeddedResources = await this.loadEmbeddedResourcesAsync();
|
|
152
|
-
if (embeddedResources) {
|
|
153
|
-
// Create a new adapter with loaded resources
|
|
154
|
-
this.provider = new EmbeddedResourcesAdapter(embeddedResources);
|
|
155
|
-
}
|
|
156
|
-
} catch (error) {
|
|
157
|
-
console.warn('Failed to load embedded resources, falling back to filesystem:', error);
|
|
158
|
-
// Fall back to filesystem mode
|
|
159
|
-
this.mode = 'filesystem';
|
|
160
|
-
this.provider = new ResourcesProviderService();
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return this.provider.initializeResources();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
async listResources(): Promise<SpecVerseResource[]> {
|
|
169
|
-
return this.provider.listResources();
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
async getResourceContent(uri: string): Promise<string> {
|
|
173
|
-
return this.provider.getResourceContent(uri);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async readResource(uri: string): Promise<MCPToolResult> {
|
|
177
|
-
return this.provider.readResource(uri);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
isResourceAvailable(uri: string): boolean {
|
|
181
|
-
return this.provider.isResourceAvailable(uri);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
getCachedResourceCount(): number {
|
|
185
|
-
return this.provider.getCachedResourceCount();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
getMode(): 'filesystem' | 'embedded' {
|
|
189
|
-
return this.mode;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
getProviderInfo(): { mode: string; type: string; resourcesInfo?: any } {
|
|
193
|
-
const info = {
|
|
194
|
-
mode: this.mode,
|
|
195
|
-
type: this.provider.constructor.name,
|
|
196
|
-
resourcesInfo: undefined as any
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
// Add provider-specific info
|
|
200
|
-
if (this.provider instanceof EmbeddedResourcesAdapter) {
|
|
201
|
-
info.resourcesInfo = this.provider.getEmbeddedResourcesInfo();
|
|
202
|
-
} else if (this.provider instanceof ResourcesProviderService) {
|
|
203
|
-
info.resourcesInfo = {
|
|
204
|
-
cached: this.provider.getCachedResourceCount()
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return info;
|
|
209
|
-
}
|
|
210
|
-
}
|
package/libs/instance-factories/tools/templates/mcp/static/src/services/LibraryToolsService.ts
DELETED
|
@@ -1,356 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LibraryToolsService
|
|
3
|
-
* Clean implementation from extracted specification
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { parse } from 'yaml';
|
|
7
|
-
import { LibrarySuggestionModel } from '../models/LibrarySuggestion.js';
|
|
8
|
-
import type { ResourceProvider } from '../interfaces/ResourceProvider.js';
|
|
9
|
-
import type {
|
|
10
|
-
LibraryCatalog,
|
|
11
|
-
LibrarySuggestion,
|
|
12
|
-
MCPToolResult,
|
|
13
|
-
PromptContext
|
|
14
|
-
} from '../types/index.js';
|
|
15
|
-
|
|
16
|
-
export class LibraryToolsService {
|
|
17
|
-
private resourcesProvider: ResourceProvider;
|
|
18
|
-
private libraryCatalog: LibraryCatalog | null = null;
|
|
19
|
-
private catalogCache: Map<string, LibrarySuggestionModel> = new Map();
|
|
20
|
-
|
|
21
|
-
constructor(resourcesProvider: ResourceProvider) {
|
|
22
|
-
this.resourcesProvider = resourcesProvider;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async getLibrarySuggestions(context: PromptContext): Promise<MCPToolResult> {
|
|
26
|
-
try {
|
|
27
|
-
// Ensure library catalog is loaded
|
|
28
|
-
if (!this.libraryCatalog) {
|
|
29
|
-
await this.loadLibraryCatalog();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (!this.libraryCatalog) {
|
|
33
|
-
throw new Error('Library catalog not available');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Extract context parameters
|
|
37
|
-
const {
|
|
38
|
-
requirements = '',
|
|
39
|
-
scale = 'business'
|
|
40
|
-
} = context;
|
|
41
|
-
|
|
42
|
-
// Analyze context and generate suggestions
|
|
43
|
-
const analysis = this.analyzeSuggestions(requirements, scale);
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
content: [{
|
|
47
|
-
type: 'text',
|
|
48
|
-
text: JSON.stringify({
|
|
49
|
-
libraries: analysis.libraries.map(lib => ({
|
|
50
|
-
name: lib.name,
|
|
51
|
-
path: lib.path,
|
|
52
|
-
type: lib.type,
|
|
53
|
-
description: lib.description,
|
|
54
|
-
ai_description: lib.ai_description,
|
|
55
|
-
expansion_factor: lib.expansion_factor,
|
|
56
|
-
complexity_level: lib.complexity_level,
|
|
57
|
-
best_for: lib.best_for
|
|
58
|
-
})),
|
|
59
|
-
reasoning: analysis.reasoning,
|
|
60
|
-
usage_examples: analysis.usage_examples,
|
|
61
|
-
total_suggestions: analysis.libraries.length,
|
|
62
|
-
scale_optimization: scale
|
|
63
|
-
}, null, 2)
|
|
64
|
-
}]
|
|
65
|
-
};
|
|
66
|
-
} catch (error) {
|
|
67
|
-
return {
|
|
68
|
-
content: [{
|
|
69
|
-
type: 'text',
|
|
70
|
-
text: `Error generating library suggestions: ${error instanceof Error ? error.message : String(error)}`
|
|
71
|
-
}],
|
|
72
|
-
isError: true
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
analyzeSuggestions(projectContext: string, scale: string): {
|
|
78
|
-
libraries: LibrarySuggestionModel[];
|
|
79
|
-
reasoning: string;
|
|
80
|
-
usage_examples: string[];
|
|
81
|
-
} {
|
|
82
|
-
if (!this.libraryCatalog) {
|
|
83
|
-
return {
|
|
84
|
-
libraries: [],
|
|
85
|
-
reasoning: 'Library catalog not available',
|
|
86
|
-
usage_examples: []
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const suggestions: LibrarySuggestionModel[] = [];
|
|
91
|
-
const reasoningParts: string[] = [];
|
|
92
|
-
const usageExamples: string[] = [];
|
|
93
|
-
|
|
94
|
-
const contextLower = projectContext.toLowerCase();
|
|
95
|
-
const allLibraries = this.getAllLibraries();
|
|
96
|
-
|
|
97
|
-
// Domain-specific analysis
|
|
98
|
-
const domainAnalysis = this.analyzeDomain(contextLower, allLibraries);
|
|
99
|
-
if (domainAnalysis.library) {
|
|
100
|
-
suggestions.push(domainAnalysis.library);
|
|
101
|
-
reasoningParts.push(domainAnalysis.reasoning);
|
|
102
|
-
usageExamples.push(domainAnalysis.usage);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Technology stack analysis
|
|
106
|
-
const techAnalysis = this.analyzeTechnology(contextLower, allLibraries);
|
|
107
|
-
if (techAnalysis.library && !suggestions.find(s => s.name === techAnalysis.library!.name)) {
|
|
108
|
-
suggestions.push(techAnalysis.library);
|
|
109
|
-
reasoningParts.push(techAnalysis.reasoning);
|
|
110
|
-
usageExamples.push(techAnalysis.usage);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Scale-based deployment analysis
|
|
114
|
-
const deploymentAnalysis = this.analyzeDeployment(scale, allLibraries);
|
|
115
|
-
if (deploymentAnalysis.library && !suggestions.find(s => s.name === deploymentAnalysis.library!.name)) {
|
|
116
|
-
suggestions.push(deploymentAnalysis.library);
|
|
117
|
-
reasoningParts.push(deploymentAnalysis.reasoning);
|
|
118
|
-
usageExamples.push(deploymentAnalysis.usage);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Authentication analysis
|
|
122
|
-
const authAnalysis = this.analyzeAuthentication(contextLower, allLibraries);
|
|
123
|
-
if (authAnalysis.library && !suggestions.find(s => s.name === authAnalysis.library!.name)) {
|
|
124
|
-
suggestions.push(authAnalysis.library);
|
|
125
|
-
reasoningParts.push(authAnalysis.reasoning);
|
|
126
|
-
usageExamples.push(authAnalysis.usage);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Default suggestions if nothing specific found
|
|
130
|
-
if (suggestions.length === 0) {
|
|
131
|
-
const defaults = allLibraries
|
|
132
|
-
.filter(lib => this.isGeneralPurpose(lib) || this.matchesScale(lib, scale))
|
|
133
|
-
.slice(0, 2);
|
|
134
|
-
|
|
135
|
-
suggestions.push(...defaults);
|
|
136
|
-
reasoningParts.push('General-purpose libraries for common patterns');
|
|
137
|
-
usageExamples.push('import:\\n - from: "@specverse/types/examples"\\n models: [User, BaseEntity]');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Sort by relevance score
|
|
141
|
-
suggestions.sort((a, b) => {
|
|
142
|
-
const aScore = a.matchesContext(projectContext, scale);
|
|
143
|
-
const bScore = b.matchesContext(projectContext, scale);
|
|
144
|
-
return bScore - aScore;
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
return {
|
|
148
|
-
libraries: suggestions.slice(0, 5), // Top 5 suggestions
|
|
149
|
-
reasoning: reasoningParts.join('; '),
|
|
150
|
-
usage_examples: usageExamples
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
private async loadLibraryCatalog(): Promise<void> {
|
|
155
|
-
try {
|
|
156
|
-
const catalogContent = await this.resourcesProvider.getResourceContent('specverse://libraries/catalog');
|
|
157
|
-
this.libraryCatalog = parse(catalogContent) as LibraryCatalog;
|
|
158
|
-
|
|
159
|
-
// Cache all library models
|
|
160
|
-
this.cacheLibraryModels();
|
|
161
|
-
} catch (error) {
|
|
162
|
-
console.error('Failed to load library catalog:', error);
|
|
163
|
-
this.libraryCatalog = this.createEmptyLibraryCatalog();
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
private cacheLibraryModels(): void {
|
|
168
|
-
if (!this.libraryCatalog) return;
|
|
169
|
-
|
|
170
|
-
const allLibraries = [
|
|
171
|
-
...Object.values(this.libraryCatalog.deployments || {}),
|
|
172
|
-
...Object.values(this.libraryCatalog.domains || {}),
|
|
173
|
-
...Object.values(this.libraryCatalog.manifests || {}),
|
|
174
|
-
...Object.values(this.libraryCatalog.types || {})
|
|
175
|
-
];
|
|
176
|
-
|
|
177
|
-
for (const library of allLibraries) {
|
|
178
|
-
try {
|
|
179
|
-
const model = LibrarySuggestionModel.create(library);
|
|
180
|
-
this.catalogCache.set(library.name, model);
|
|
181
|
-
} catch (error) {
|
|
182
|
-
console.warn(`Failed to cache library ${library.name}:`, error);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
private getAllLibraries(): LibrarySuggestionModel[] {
|
|
188
|
-
return Array.from(this.catalogCache.values());
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
private analyzeDomain(context: string, libraries: LibrarySuggestionModel[]): {
|
|
192
|
-
library?: LibrarySuggestionModel;
|
|
193
|
-
reasoning: string;
|
|
194
|
-
usage: string;
|
|
195
|
-
} {
|
|
196
|
-
if (context.includes('ecommerce') || context.includes('store') || context.includes('shop')) {
|
|
197
|
-
const ecommerce = libraries.find(lib => lib.name.includes('ecommerce'));
|
|
198
|
-
if (ecommerce) {
|
|
199
|
-
return {
|
|
200
|
-
library: ecommerce,
|
|
201
|
-
reasoning: 'E-commerce domain detected',
|
|
202
|
-
usage: 'import:\\n - from: "@specverse/domains/ecommerce"\\n models: [Product, Order, Customer]'
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (context.includes('healthcare') || context.includes('medical') || context.includes('patient')) {
|
|
208
|
-
const healthcare = libraries.find(lib => lib.name.includes('healthcare'));
|
|
209
|
-
if (healthcare) {
|
|
210
|
-
return {
|
|
211
|
-
library: healthcare,
|
|
212
|
-
reasoning: 'Healthcare domain detected',
|
|
213
|
-
usage: 'import:\\n - from: "@specverse/domains/healthcare"\\n models: [Patient, Provider, Appointment]'
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return { reasoning: 'No specific domain patterns detected', usage: '' };
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
private analyzeTechnology(context: string, libraries: LibrarySuggestionModel[]): {
|
|
222
|
-
library?: LibrarySuggestionModel;
|
|
223
|
-
reasoning: string;
|
|
224
|
-
usage: string;
|
|
225
|
-
} {
|
|
226
|
-
if (context.includes('nextjs') || context.includes('next.js') || context.includes('react')) {
|
|
227
|
-
const nextjs = libraries.find(lib => lib.name.includes('nextjs'));
|
|
228
|
-
if (nextjs) {
|
|
229
|
-
return {
|
|
230
|
-
library: nextjs,
|
|
231
|
-
reasoning: 'Next.js framework detected',
|
|
232
|
-
usage: 'import:\\n - from: "@specverse/manifests/nextjs"\\n manifests: [nextjs-config]'
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (context.includes('postgresql') || context.includes('postgres')) {
|
|
238
|
-
const postgres = libraries.find(lib => lib.name.includes('postgresql'));
|
|
239
|
-
if (postgres) {
|
|
240
|
-
return {
|
|
241
|
-
library: postgres,
|
|
242
|
-
reasoning: 'PostgreSQL database detected',
|
|
243
|
-
usage: 'import:\\n - from: "@specverse/manifests/postgresql"\\n manifests: [postgres-config]'
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
return { reasoning: 'No specific technology patterns detected', usage: '' };
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
private analyzeDeployment(scale: string, libraries: LibrarySuggestionModel[]): {
|
|
252
|
-
library?: LibrarySuggestionModel;
|
|
253
|
-
reasoning: string;
|
|
254
|
-
usage: string;
|
|
255
|
-
} {
|
|
256
|
-
switch (scale) {
|
|
257
|
-
case 'personal':
|
|
258
|
-
const personal = libraries.find(lib => lib.name.includes('jamstack') || lib.name.includes('monolith'));
|
|
259
|
-
if (personal) {
|
|
260
|
-
return {
|
|
261
|
-
library: personal,
|
|
262
|
-
reasoning: 'Personal scale: simple deployment recommended',
|
|
263
|
-
usage: `import:\\n - from: "@specverse/deployments/${personal.name}"\\n deployments: [development]`
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
break;
|
|
267
|
-
|
|
268
|
-
case 'enterprise':
|
|
269
|
-
const enterprise = libraries.find(lib => lib.name.includes('enterprise') || lib.name.includes('microservices'));
|
|
270
|
-
if (enterprise) {
|
|
271
|
-
return {
|
|
272
|
-
library: enterprise,
|
|
273
|
-
reasoning: 'Enterprise scale: distributed architecture recommended',
|
|
274
|
-
usage: `import:\\n - from: "@specverse/deployments/${enterprise.name}"\\n deployments: [production-cluster]`
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
break;
|
|
278
|
-
|
|
279
|
-
default: // business
|
|
280
|
-
const business = libraries.find(lib => lib.name.includes('microservices') || lib.name.includes('monolith'));
|
|
281
|
-
if (business) {
|
|
282
|
-
return {
|
|
283
|
-
library: business,
|
|
284
|
-
reasoning: 'Business scale: scalable deployment recommended',
|
|
285
|
-
usage: `import:\\n - from: "@specverse/deployments/${business.name}"\\n deployments: [production]`
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
break;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return { reasoning: 'No deployment pattern match found', usage: '' };
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
private analyzeAuthentication(context: string, libraries: LibrarySuggestionModel[]): {
|
|
295
|
-
library?: LibrarySuggestionModel;
|
|
296
|
-
reasoning: string;
|
|
297
|
-
usage: string;
|
|
298
|
-
} {
|
|
299
|
-
if (context.includes('authentication') || context.includes('auth') || context.includes('login')) {
|
|
300
|
-
const oauth = libraries.find(lib => lib.name.includes('oauth'));
|
|
301
|
-
if (oauth) {
|
|
302
|
-
return {
|
|
303
|
-
library: oauth,
|
|
304
|
-
reasoning: 'Authentication features detected',
|
|
305
|
-
usage: 'import:\\n - from: "@specverse/manifests/oauth"\\n manifests: [oauth-config]'
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return { reasoning: 'No authentication patterns detected', usage: '' };
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
private isGeneralPurpose(library: LibrarySuggestionModel): boolean {
|
|
314
|
-
return library.name.includes('examples') ||
|
|
315
|
-
library.name.includes('lib') ||
|
|
316
|
-
library.type === 'type';
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
private matchesScale(library: LibrarySuggestionModel, scale: string): boolean {
|
|
320
|
-
const scaleComplexity = this.getScaleComplexity(scale);
|
|
321
|
-
const libComplexity = this.getComplexityScore(library.complexity_level);
|
|
322
|
-
return Math.abs(libComplexity - scaleComplexity) <= 1;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
private getScaleComplexity(scale: string): number {
|
|
326
|
-
switch (scale) {
|
|
327
|
-
case 'personal': return 1;
|
|
328
|
-
case 'business': return 2;
|
|
329
|
-
case 'enterprise': return 3;
|
|
330
|
-
default: return 2;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
private getComplexityScore(complexity: string): number {
|
|
335
|
-
switch (complexity) {
|
|
336
|
-
case 'low': return 1;
|
|
337
|
-
case 'medium': return 2;
|
|
338
|
-
case 'high': return 3;
|
|
339
|
-
default: return 2;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
private createEmptyLibraryCatalog(): LibraryCatalog {
|
|
344
|
-
return {
|
|
345
|
-
version: '3.1.0',
|
|
346
|
-
generated_at: new Date(),
|
|
347
|
-
generated_from: 'embedded',
|
|
348
|
-
ai_optimization: false,
|
|
349
|
-
total_libraries: 0,
|
|
350
|
-
deployments: {},
|
|
351
|
-
domains: {},
|
|
352
|
-
manifests: {},
|
|
353
|
-
types: {}
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
}
|