fraim 2.0.100
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 +445 -0
- package/bin/fraim.js +23 -0
- package/dist/src/cli/api/get-provider-client.js +41 -0
- package/dist/src/cli/api/provider-client.js +107 -0
- package/dist/src/cli/commands/add-ide.js +430 -0
- package/dist/src/cli/commands/add-provider.js +233 -0
- package/dist/src/cli/commands/doctor.js +149 -0
- package/dist/src/cli/commands/init-project.js +301 -0
- package/dist/src/cli/commands/list-overridable.js +184 -0
- package/dist/src/cli/commands/list.js +57 -0
- package/dist/src/cli/commands/login.js +84 -0
- package/dist/src/cli/commands/mcp.js +15 -0
- package/dist/src/cli/commands/migrate-project-fraim.js +42 -0
- package/dist/src/cli/commands/override.js +177 -0
- package/dist/src/cli/commands/setup.js +651 -0
- package/dist/src/cli/commands/sync.js +162 -0
- package/dist/src/cli/commands/test-mcp.js +171 -0
- package/dist/src/cli/doctor/check-runner.js +199 -0
- package/dist/src/cli/doctor/checks/global-setup-checks.js +220 -0
- package/dist/src/cli/doctor/checks/ide-config-checks.js +250 -0
- package/dist/src/cli/doctor/checks/mcp-connectivity-checks.js +381 -0
- package/dist/src/cli/doctor/checks/project-setup-checks.js +282 -0
- package/dist/src/cli/doctor/checks/scripts-checks.js +157 -0
- package/dist/src/cli/doctor/checks/workflow-checks.js +251 -0
- package/dist/src/cli/doctor/reporters/console-reporter.js +96 -0
- package/dist/src/cli/doctor/reporters/json-reporter.js +11 -0
- package/dist/src/cli/doctor/types.js +6 -0
- package/dist/src/cli/fraim.js +100 -0
- package/dist/src/cli/internal/device-flow-service.js +83 -0
- package/dist/src/cli/mcp/ide-formats.js +243 -0
- package/dist/src/cli/mcp/mcp-server-builder.js +48 -0
- package/dist/src/cli/mcp/mcp-server-registry.js +160 -0
- package/dist/src/cli/mcp/types.js +3 -0
- package/dist/src/cli/providers/local-provider-registry.js +166 -0
- package/dist/src/cli/providers/provider-registry.js +230 -0
- package/dist/src/cli/setup/auto-mcp-setup.js +331 -0
- package/dist/src/cli/setup/codex-local-config.js +37 -0
- package/dist/src/cli/setup/first-run.js +242 -0
- package/dist/src/cli/setup/ide-detector.js +179 -0
- package/dist/src/cli/setup/mcp-config-generator.js +192 -0
- package/dist/src/cli/setup/provider-prompts.js +339 -0
- package/dist/src/cli/utils/agent-adapters.js +126 -0
- package/dist/src/cli/utils/digest-utils.js +47 -0
- package/dist/src/cli/utils/fraim-gitignore.js +40 -0
- package/dist/src/cli/utils/platform-detection.js +258 -0
- package/dist/src/cli/utils/project-bootstrap.js +93 -0
- package/dist/src/cli/utils/remote-sync.js +315 -0
- package/dist/src/cli/utils/script-sync-utils.js +221 -0
- package/dist/src/cli/utils/version-utils.js +32 -0
- package/dist/src/core/ai-mentor.js +230 -0
- package/dist/src/core/config-loader.js +114 -0
- package/dist/src/core/config-writer.js +75 -0
- package/dist/src/core/types.js +23 -0
- package/dist/src/core/utils/git-utils.js +95 -0
- package/dist/src/core/utils/include-resolver.js +92 -0
- package/dist/src/core/utils/inheritance-parser.js +288 -0
- package/dist/src/core/utils/job-parser.js +176 -0
- package/dist/src/core/utils/local-registry-resolver.js +616 -0
- package/dist/src/core/utils/object-utils.js +11 -0
- package/dist/src/core/utils/project-fraim-migration.js +103 -0
- package/dist/src/core/utils/project-fraim-paths.js +38 -0
- package/dist/src/core/utils/provider-utils.js +18 -0
- package/dist/src/core/utils/server-startup.js +34 -0
- package/dist/src/core/utils/stub-generator.js +147 -0
- package/dist/src/core/utils/workflow-parser.js +174 -0
- package/dist/src/local-mcp-server/learning-context-builder.js +229 -0
- package/dist/src/local-mcp-server/stdio-server.js +1698 -0
- package/dist/src/local-mcp-server/usage-collector.js +264 -0
- package/index.js +85 -0
- package/package.json +139 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Local provider registry - fallback when server is unavailable
|
|
3
|
+
// This is the original provider metadata that was in provider-registry.ts
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getLocalProvider = getLocalProvider;
|
|
6
|
+
exports.getAllLocalProviders = getAllLocalProviders;
|
|
7
|
+
exports.getAllLocalProviderIds = getAllLocalProviderIds;
|
|
8
|
+
exports.isValidLocalProviderId = isValidLocalProviderId;
|
|
9
|
+
exports.getLocalProviderDisplayName = getLocalProviderDisplayName;
|
|
10
|
+
exports.getLocalProviderSetupInstructions = getLocalProviderSetupInstructions;
|
|
11
|
+
exports.getLocalProviderConfigRequirements = getLocalProviderConfigRequirements;
|
|
12
|
+
exports.localRequiresAdditionalConfig = localRequiresAdditionalConfig;
|
|
13
|
+
exports.validateLocalProviderConfig = validateLocalProviderConfig;
|
|
14
|
+
exports.getLocalProvidersWithCapability = getLocalProvidersWithCapability;
|
|
15
|
+
exports.getLocalProviderIdsWithCapability = getLocalProviderIdsWithCapability;
|
|
16
|
+
exports.localProviderHasCapability = localProviderHasCapability;
|
|
17
|
+
// Local provider definitions (fallback data)
|
|
18
|
+
const LOCAL_PROVIDERS = [
|
|
19
|
+
{
|
|
20
|
+
id: 'github',
|
|
21
|
+
displayName: 'GitHub',
|
|
22
|
+
description: 'GitHub repository and issue management',
|
|
23
|
+
capabilities: ['code', 'issues', 'integrated'],
|
|
24
|
+
docsUrl: 'https://docs.github.com',
|
|
25
|
+
setupInstructions: 'Create a Personal Access Token at https://github.com/settings/tokens',
|
|
26
|
+
hasAdditionalConfig: false,
|
|
27
|
+
mcpServer: {
|
|
28
|
+
type: 'http',
|
|
29
|
+
url: 'https://api.githubcopilot.com/mcp/',
|
|
30
|
+
authHeaderTemplate: 'Bearer {token}'
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'gitlab',
|
|
35
|
+
displayName: 'GitLab',
|
|
36
|
+
description: 'GitLab repository and issue management',
|
|
37
|
+
capabilities: ['code', 'issues', 'integrated'],
|
|
38
|
+
docsUrl: 'https://docs.gitlab.com',
|
|
39
|
+
setupInstructions: 'Create a Personal Access Token in your GitLab settings',
|
|
40
|
+
hasAdditionalConfig: false,
|
|
41
|
+
mcpServer: {
|
|
42
|
+
type: 'http',
|
|
43
|
+
url: 'https://gitlab.com/api/v4/mcp',
|
|
44
|
+
authHeaderTemplate: 'Bearer {token}'
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'ado',
|
|
49
|
+
displayName: 'Azure DevOps',
|
|
50
|
+
description: 'Azure DevOps repository and issue management',
|
|
51
|
+
capabilities: ['code', 'issues', 'integrated'],
|
|
52
|
+
docsUrl: 'https://docs.microsoft.com/azure/devops',
|
|
53
|
+
setupInstructions: 'Create a Personal Access Token in Azure DevOps',
|
|
54
|
+
hasAdditionalConfig: true,
|
|
55
|
+
mcpServer: {
|
|
56
|
+
type: 'stdio',
|
|
57
|
+
command: 'npx',
|
|
58
|
+
args: ['-y', '@azure-devops/mcp', '{config.organization}', '--authentication', 'envvar'],
|
|
59
|
+
envTemplate: {
|
|
60
|
+
ADO_MCP_AUTH_TOKEN: '{token}'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: 'jira',
|
|
66
|
+
displayName: 'Jira',
|
|
67
|
+
description: 'Jira issue tracking and project management',
|
|
68
|
+
capabilities: ['issues'],
|
|
69
|
+
docsUrl: 'https://support.atlassian.com/jira',
|
|
70
|
+
setupInstructions: 'Create an API token at https://id.atlassian.com/manage-profile/security/api-tokens',
|
|
71
|
+
hasAdditionalConfig: true,
|
|
72
|
+
mcpServer: {
|
|
73
|
+
type: 'stdio',
|
|
74
|
+
command: 'uvx',
|
|
75
|
+
args: ['mcp-atlassian'],
|
|
76
|
+
envTemplate: {
|
|
77
|
+
JIRA_URL: '{config.baseUrl}',
|
|
78
|
+
JIRA_USERNAME: '{config.email}',
|
|
79
|
+
JIRA_API_TOKEN: '{token}'
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
];
|
|
84
|
+
const ADO_CONFIG_REQUIREMENTS = [
|
|
85
|
+
{
|
|
86
|
+
key: 'organization',
|
|
87
|
+
displayName: 'Azure DevOps Organization',
|
|
88
|
+
description: 'Your Azure DevOps organization name (e.g., contoso)',
|
|
89
|
+
required: true,
|
|
90
|
+
type: 'string',
|
|
91
|
+
cliOptionName: 'organization'
|
|
92
|
+
}
|
|
93
|
+
];
|
|
94
|
+
const JIRA_CONFIG_REQUIREMENTS = [
|
|
95
|
+
{
|
|
96
|
+
key: 'baseUrl',
|
|
97
|
+
displayName: 'Jira Instance URL',
|
|
98
|
+
description: 'Your Jira instance URL (e.g., mycompany.atlassian.net)',
|
|
99
|
+
required: true,
|
|
100
|
+
type: 'url',
|
|
101
|
+
cliOptionName: 'url'
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
key: 'email',
|
|
105
|
+
displayName: 'Email Address',
|
|
106
|
+
description: 'Your Jira account email address',
|
|
107
|
+
required: true,
|
|
108
|
+
type: 'email'
|
|
109
|
+
}
|
|
110
|
+
];
|
|
111
|
+
function getLocalProvider(id) {
|
|
112
|
+
return LOCAL_PROVIDERS.find(p => p.id === id);
|
|
113
|
+
}
|
|
114
|
+
function getAllLocalProviders() {
|
|
115
|
+
return [...LOCAL_PROVIDERS];
|
|
116
|
+
}
|
|
117
|
+
function getAllLocalProviderIds() {
|
|
118
|
+
return LOCAL_PROVIDERS.map(p => p.id);
|
|
119
|
+
}
|
|
120
|
+
function isValidLocalProviderId(id) {
|
|
121
|
+
return LOCAL_PROVIDERS.some(p => p.id === id);
|
|
122
|
+
}
|
|
123
|
+
function getLocalProviderDisplayName(providerId) {
|
|
124
|
+
const provider = getLocalProvider(providerId);
|
|
125
|
+
return provider?.displayName || providerId;
|
|
126
|
+
}
|
|
127
|
+
function getLocalProviderSetupInstructions(providerId) {
|
|
128
|
+
const provider = getLocalProvider(providerId);
|
|
129
|
+
return provider?.setupInstructions || '';
|
|
130
|
+
}
|
|
131
|
+
function getLocalProviderConfigRequirements(providerId) {
|
|
132
|
+
if (providerId === 'ado') {
|
|
133
|
+
return ADO_CONFIG_REQUIREMENTS;
|
|
134
|
+
}
|
|
135
|
+
if (providerId === 'jira') {
|
|
136
|
+
return JIRA_CONFIG_REQUIREMENTS;
|
|
137
|
+
}
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
function localRequiresAdditionalConfig(providerId) {
|
|
141
|
+
return getLocalProviderConfigRequirements(providerId).length > 0;
|
|
142
|
+
}
|
|
143
|
+
function validateLocalProviderConfig(providerId, config) {
|
|
144
|
+
const requirements = getLocalProviderConfigRequirements(providerId);
|
|
145
|
+
const missing = [];
|
|
146
|
+
for (const req of requirements) {
|
|
147
|
+
if (req.required && !config[req.key]) {
|
|
148
|
+
missing.push(req.key);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
valid: missing.length === 0,
|
|
153
|
+
missing
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function getLocalProvidersWithCapability(capability) {
|
|
157
|
+
return LOCAL_PROVIDERS.filter(provider => provider.capabilities.includes(capability));
|
|
158
|
+
}
|
|
159
|
+
function getLocalProviderIdsWithCapability(capability) {
|
|
160
|
+
const providers = getLocalProvidersWithCapability(capability);
|
|
161
|
+
return providers.map(p => p.id);
|
|
162
|
+
}
|
|
163
|
+
function localProviderHasCapability(providerId, capability) {
|
|
164
|
+
const provider = getLocalProvider(providerId);
|
|
165
|
+
return provider ? provider.capabilities.includes(capability) : false;
|
|
166
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Provider Registry - Client stub that fetches from server
|
|
3
|
+
// This file maintains the same API as before but calls the server instead of using local data
|
|
4
|
+
// Falls back to local registry when server is unavailable (for tests and offline usage)
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getProvider = getProvider;
|
|
40
|
+
exports.getAllProviders = getAllProviders;
|
|
41
|
+
exports.getAllProviderIds = getAllProviderIds;
|
|
42
|
+
exports.isValidProviderId = isValidProviderId;
|
|
43
|
+
exports.getProviderDisplayName = getProviderDisplayName;
|
|
44
|
+
exports.getProviderSetupInstructions = getProviderSetupInstructions;
|
|
45
|
+
exports.getProviderConfigRequirements = getProviderConfigRequirements;
|
|
46
|
+
exports.requiresAdditionalConfig = requiresAdditionalConfig;
|
|
47
|
+
exports.validateProviderConfig = validateProviderConfig;
|
|
48
|
+
exports.getProvidersWithCapability = getProvidersWithCapability;
|
|
49
|
+
exports.getProviderIdsWithCapability = getProviderIdsWithCapability;
|
|
50
|
+
exports.providerHasCapability = providerHasCapability;
|
|
51
|
+
const get_provider_client_1 = require("../api/get-provider-client");
|
|
52
|
+
const local = __importStar(require("./local-provider-registry"));
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// CACHE
|
|
55
|
+
// ============================================================================
|
|
56
|
+
let cachedProviders = null;
|
|
57
|
+
const schemaCache = new Map();
|
|
58
|
+
let useLocalFallback = false;
|
|
59
|
+
async function fetchProviders() {
|
|
60
|
+
// Don't use cache in test environment to avoid stale data
|
|
61
|
+
const useCache = process.env.NODE_ENV !== 'test';
|
|
62
|
+
if (useCache && cachedProviders)
|
|
63
|
+
return cachedProviders;
|
|
64
|
+
// In test environment, always try server first (don't persist fallback flag)
|
|
65
|
+
const shouldTryServer = process.env.NODE_ENV === 'test' || !useLocalFallback;
|
|
66
|
+
// Try server first
|
|
67
|
+
if (shouldTryServer) {
|
|
68
|
+
try {
|
|
69
|
+
const client = (0, get_provider_client_1.getProviderClient)();
|
|
70
|
+
const providers = await client.getAllProviders();
|
|
71
|
+
if (useCache) {
|
|
72
|
+
cachedProviders = providers;
|
|
73
|
+
}
|
|
74
|
+
return providers;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Server unavailable - use local fallback
|
|
78
|
+
console.warn('⚠️ Using local provider registry (server unavailable)');
|
|
79
|
+
// Only persist fallback flag in non-test environments
|
|
80
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
81
|
+
useLocalFallback = true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Use local fallback
|
|
86
|
+
const providers = local.getAllLocalProviders();
|
|
87
|
+
if (useCache) {
|
|
88
|
+
cachedProviders = providers;
|
|
89
|
+
}
|
|
90
|
+
return providers;
|
|
91
|
+
}
|
|
92
|
+
async function fetchProviderSchema(id) {
|
|
93
|
+
if (schemaCache.has(id)) {
|
|
94
|
+
return schemaCache.get(id);
|
|
95
|
+
}
|
|
96
|
+
// In test environment, always try server first (don't persist fallback flag)
|
|
97
|
+
const shouldTryServer = process.env.NODE_ENV === 'test' || !useLocalFallback;
|
|
98
|
+
// Try server first
|
|
99
|
+
if (shouldTryServer) {
|
|
100
|
+
try {
|
|
101
|
+
const client = (0, get_provider_client_1.getProviderClient)();
|
|
102
|
+
const schema = await client.getProviderSchema(id);
|
|
103
|
+
schemaCache.set(id, schema.configRequirements);
|
|
104
|
+
return schema.configRequirements;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
// Server unavailable - use local fallback
|
|
108
|
+
// Only persist fallback flag in non-test environments
|
|
109
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
110
|
+
useLocalFallback = true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Use local fallback
|
|
115
|
+
const requirements = local.getLocalProviderConfigRequirements(id);
|
|
116
|
+
schemaCache.set(id, requirements);
|
|
117
|
+
return requirements;
|
|
118
|
+
}
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// REGISTRY LOOKUP FUNCTIONS (Same API as before, but async)
|
|
121
|
+
// ============================================================================
|
|
122
|
+
async function getProvider(id) {
|
|
123
|
+
// In test environment, always try server first (don't persist fallback flag)
|
|
124
|
+
const shouldTryServer = process.env.NODE_ENV === 'test' || !useLocalFallback;
|
|
125
|
+
// Try server first
|
|
126
|
+
if (shouldTryServer) {
|
|
127
|
+
try {
|
|
128
|
+
const client = (0, get_provider_client_1.getProviderClient)();
|
|
129
|
+
const provider = await client.getProvider(id);
|
|
130
|
+
return provider || undefined;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
// Server unavailable - use local fallback
|
|
134
|
+
console.warn('⚠️ Using local provider registry (server unavailable)');
|
|
135
|
+
// Only persist fallback flag in non-test environments
|
|
136
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
137
|
+
useLocalFallback = true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Use local fallback
|
|
142
|
+
const provider = local.getLocalProvider(id);
|
|
143
|
+
return provider;
|
|
144
|
+
}
|
|
145
|
+
async function getAllProviders() {
|
|
146
|
+
return await fetchProviders();
|
|
147
|
+
}
|
|
148
|
+
async function getAllProviderIds() {
|
|
149
|
+
// In test environment, always try server first (don't persist fallback flag)
|
|
150
|
+
const shouldTryServer = process.env.NODE_ENV === 'test' || !useLocalFallback;
|
|
151
|
+
// Try server first
|
|
152
|
+
if (shouldTryServer) {
|
|
153
|
+
try {
|
|
154
|
+
const client = (0, get_provider_client_1.getProviderClient)();
|
|
155
|
+
return await client.getAllProviderIds();
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
// Server unavailable - use local fallback
|
|
159
|
+
// Only persist fallback flag in non-test environments
|
|
160
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
161
|
+
useLocalFallback = true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Use local fallback
|
|
166
|
+
return local.getAllLocalProviderIds();
|
|
167
|
+
}
|
|
168
|
+
async function isValidProviderId(id) {
|
|
169
|
+
const providers = await fetchProviders();
|
|
170
|
+
return providers.some(p => p.id === id);
|
|
171
|
+
}
|
|
172
|
+
async function getProviderDisplayName(providerId) {
|
|
173
|
+
const provider = await getProvider(providerId);
|
|
174
|
+
return provider?.displayName || providerId;
|
|
175
|
+
}
|
|
176
|
+
async function getProviderSetupInstructions(providerId) {
|
|
177
|
+
const provider = await getProvider(providerId);
|
|
178
|
+
return provider?.setupInstructions || '';
|
|
179
|
+
}
|
|
180
|
+
async function getProviderConfigRequirements(providerId) {
|
|
181
|
+
return await fetchProviderSchema(providerId);
|
|
182
|
+
}
|
|
183
|
+
async function requiresAdditionalConfig(providerId) {
|
|
184
|
+
const requirements = await getProviderConfigRequirements(providerId);
|
|
185
|
+
return requirements.length > 0;
|
|
186
|
+
}
|
|
187
|
+
async function validateProviderConfig(providerId, config) {
|
|
188
|
+
const requirements = await getProviderConfigRequirements(providerId);
|
|
189
|
+
const missing = [];
|
|
190
|
+
for (const req of requirements) {
|
|
191
|
+
if (req.required && !config[req.key]) {
|
|
192
|
+
missing.push(req.key);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
valid: missing.length === 0,
|
|
197
|
+
missing
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// CAPABILITY FILTERING FUNCTIONS
|
|
202
|
+
// ============================================================================
|
|
203
|
+
async function getProvidersWithCapability(capability) {
|
|
204
|
+
// In test environment, always try server first (don't persist fallback flag)
|
|
205
|
+
const shouldTryServer = process.env.NODE_ENV === 'test' || !useLocalFallback;
|
|
206
|
+
// Try server first
|
|
207
|
+
if (shouldTryServer) {
|
|
208
|
+
try {
|
|
209
|
+
const client = (0, get_provider_client_1.getProviderClient)();
|
|
210
|
+
return await client.getProvidersWithCapability(capability);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
// Server unavailable - use local fallback
|
|
214
|
+
// Only persist fallback flag in non-test environments
|
|
215
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
216
|
+
useLocalFallback = true;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Use local fallback
|
|
221
|
+
return local.getLocalProvidersWithCapability(capability);
|
|
222
|
+
}
|
|
223
|
+
async function getProviderIdsWithCapability(capability) {
|
|
224
|
+
const providers = await getProvidersWithCapability(capability);
|
|
225
|
+
return providers.map(p => p.id);
|
|
226
|
+
}
|
|
227
|
+
async function providerHasCapability(providerId, capability) {
|
|
228
|
+
const provider = await getProvider(providerId);
|
|
229
|
+
return provider ? provider.capabilities.includes(capability) : false;
|
|
230
|
+
}
|