fraim-hub 2.0.204
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 +467 -0
- package/bin/fraim-hub.js +17 -0
- package/dist/src/ai-hub/brand-store.js +17 -0
- package/dist/src/ai-hub/catalog.js +412 -0
- package/dist/src/ai-hub/cert-store.js +70 -0
- package/dist/src/ai-hub/cli.js +212 -0
- package/dist/src/ai-hub/configured-agents.js +283 -0
- package/dist/src/ai-hub/conversation-store.js +428 -0
- package/dist/src/ai-hub/desktop-main.js +449 -0
- package/dist/src/ai-hub/hosts.js +1669 -0
- package/dist/src/ai-hub/hub-latest-version.js +52 -0
- package/dist/src/ai-hub/hub-launch-decision.js +57 -0
- package/dist/src/ai-hub/hub-runtime-file.js +43 -0
- package/dist/src/ai-hub/managed-browser.js +269 -0
- package/dist/src/ai-hub/manager-turns.js +64 -0
- package/dist/src/ai-hub/office-sideload.js +156 -0
- package/dist/src/ai-hub/openclaw-bridge.js +250 -0
- package/dist/src/ai-hub/preferences.js +201 -0
- package/dist/src/ai-hub/remote-hub-gateway.js +88 -0
- package/dist/src/ai-hub/server.js +4013 -0
- package/dist/src/ai-hub/types.js +2 -0
- package/dist/src/ai-hub/url-safety.js +19 -0
- package/dist/src/api/admin/payments.js +33 -0
- package/dist/src/api/admin/sales-leads.js +21 -0
- package/dist/src/api/payment/create-session.js +338 -0
- package/dist/src/api/payment/dashboard-link.js +149 -0
- package/dist/src/api/payment/session-details.js +31 -0
- package/dist/src/api/payment/webhook.js +587 -0
- package/dist/src/api/sales/contact.js +44 -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 +462 -0
- package/dist/src/cli/fraim-hub.js +50 -0
- package/dist/src/cli/internal/device-flow-service.js +83 -0
- package/dist/src/cli/mcp/command-resolution.js +81 -0
- package/dist/src/cli/mcp/fraim-mcp-latest-launcher.js +136 -0
- package/dist/src/cli/mcp/ide-formats.js +317 -0
- package/dist/src/cli/mcp/mcp-server-builder.js +48 -0
- package/dist/src/cli/mcp/mcp-server-registry.js +173 -0
- package/dist/src/cli/providers/local-provider-registry.js +165 -0
- package/dist/src/cli/providers/provider-registry.js +230 -0
- package/dist/src/cli/setup/claude-code-telemetry.js +59 -0
- package/dist/src/cli/setup/codex-local-config.js +37 -0
- package/dist/src/cli/setup/ide-detector.js +383 -0
- package/dist/src/cli/setup/ide-global-integration.js +100 -0
- package/dist/src/cli/setup/ide-invocation-surfaces.js +160 -0
- package/dist/src/cli/setup/mcp-config-generator.js +225 -0
- package/dist/src/cli/setup/provider-prompts.js +339 -0
- package/dist/src/cli/utils/managed-agent-paths.js +118 -0
- package/dist/src/cli/utils/script-sync-utils.js +221 -0
- package/dist/src/cli/utils/user-config.js +100 -0
- package/dist/src/cli/utils/version-utils.js +35 -0
- package/dist/src/config/ai-manager-hiring.js +121 -0
- package/dist/src/config/feature-flags.js +25 -0
- package/dist/src/config/persona-capability-bundles.js +277 -0
- package/dist/src/config/persona-hiring.js +270 -0
- package/dist/src/config/portfolio-slug-overrides.js +17 -0
- package/dist/src/config/pricing.js +37 -0
- package/dist/src/config/stripe.js +43 -0
- package/dist/src/core/brand-store.js +232 -0
- package/dist/src/core/quality-evidence.js +331 -0
- package/dist/src/core/utils/git-utils.js +194 -0
- package/dist/src/core/utils/ports.js +32 -0
- package/dist/src/core/utils/project-fraim-paths.js +220 -0
- package/dist/src/db/payment-repository.js +61 -0
- package/dist/src/first-run/types.js +93 -0
- package/dist/src/fraim/db-service.js +2409 -0
- package/dist/src/local-mcp-server/agent-token-prices.js +167 -0
- package/dist/src/local-mcp-server/learning-context-builder.js +975 -0
- package/dist/src/middleware/rate-limit.js +110 -0
- package/dist/src/models/payment.js +2 -0
- package/dist/src/routes/payment-routes.js +186 -0
- package/dist/src/routes/persona-catalog-routes.js +84 -0
- package/dist/src/services/dashboard-access.js +27 -0
- package/dist/src/services/email-service.js +951 -0
- package/dist/src/services/persona-entitlement-service.js +352 -0
- package/dist/src/services/workspace-identity.js +21 -0
- package/dist/src/types/analytics.js +2 -0
- package/dist/src/utils/payment-calculator.js +52 -0
- package/extensions/office-word/favicon.ico +0 -0
- package/extensions/office-word/icon-64.png +0 -0
- package/extensions/office-word/manifest.xml +33 -0
- package/extensions/office-word/taskpane.html +242 -0
- package/index.js +85 -0
- package/package.json +106 -0
- package/public/ai-hub/index.html +910 -0
- package/public/ai-hub/powerpoint-taskpane/icon-64.png +0 -0
- package/public/ai-hub/powerpoint-taskpane/index.html +236 -0
- package/public/ai-hub/powerpoint-taskpane/manifest.xml +30 -0
- package/public/ai-hub/review.css +444 -0
- package/public/ai-hub/script.js +11737 -0
- package/public/ai-hub/styles.css +5102 -0
- package/public/first-run/error-frame.js +100 -0
- package/public/first-run/index.html +35 -0
- package/public/first-run/script.js +739 -0
- package/public/first-run/styles.css +929 -0
- package/public/portfolio/ashley.html +523 -0
- package/public/portfolio/auditya.html +83 -0
- package/public/portfolio/banke.html +83 -0
- package/public/portfolio/beza.html +659 -0
- package/public/portfolio/careena.html +632 -0
- package/public/portfolio/casey.html +568 -0
- package/public/portfolio/celia.html +490 -0
- package/public/portfolio/deidre.html +642 -0
- package/public/portfolio/gautam.html +597 -0
- package/public/portfolio/hari.html +469 -0
- package/public/portfolio/huxley.html +1354 -0
- package/public/portfolio/index.html +741 -0
- package/public/portfolio/maestro.html +518 -0
- package/public/portfolio/mandy.html +590 -0
- package/public/portfolio/mona.html +597 -0
- package/public/portfolio/pam.html +887 -0
- package/public/portfolio/procella.html +107 -0
- package/public/portfolio/qasm.html +569 -0
- package/public/portfolio/ricardo.html +489 -0
- package/public/portfolio/sade.html +560 -0
- package/public/portfolio/sam.html +654 -0
- package/public/portfolio/sechar.html +580 -0
- package/public/portfolio/sreya.html +599 -0
- package/public/portfolio/swen.html +601 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BASE_MCP_SERVERS = void 0;
|
|
4
|
+
exports.buildProviderMCPServer = buildProviderMCPServer;
|
|
5
|
+
exports.getBaseMCPServer = getBaseMCPServer;
|
|
6
|
+
exports.getProviderMCPServerIds = getProviderMCPServerIds;
|
|
7
|
+
exports.getAllMCPServerIds = getAllMCPServerIds;
|
|
8
|
+
exports.isProviderServer = isProviderServer;
|
|
9
|
+
exports.isHTTPServer = isHTTPServer;
|
|
10
|
+
exports.buildAllBaseServers = buildAllBaseServers;
|
|
11
|
+
const provider_registry_1 = require("../providers/provider-registry");
|
|
12
|
+
const command_resolution_1 = require("./command-resolution");
|
|
13
|
+
const fraim_mcp_latest_launcher_1 = require("./fraim-mcp-latest-launcher");
|
|
14
|
+
exports.BASE_MCP_SERVERS = [
|
|
15
|
+
{
|
|
16
|
+
id: 'git',
|
|
17
|
+
name: 'Git',
|
|
18
|
+
description: 'Git repository operations (commit, branch, merge, etc.)',
|
|
19
|
+
buildServer: () => ({
|
|
20
|
+
command: (0, command_resolution_1.resolveManagedCommand)('npx'),
|
|
21
|
+
args: ['-y', '@cyanheads/git-mcp-server']
|
|
22
|
+
})
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'playwright',
|
|
26
|
+
name: 'Playwright',
|
|
27
|
+
description: 'Browser automation and testing',
|
|
28
|
+
buildServer: () => ({
|
|
29
|
+
command: (0, command_resolution_1.resolveManagedCommand)('npx'),
|
|
30
|
+
args: ['-y', '@playwright/mcp']
|
|
31
|
+
})
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'fraim',
|
|
35
|
+
name: 'FRAIM',
|
|
36
|
+
description: 'FRAIM job orchestration and mentoring',
|
|
37
|
+
buildServer: (fraimKey) => {
|
|
38
|
+
const launcher = (0, fraim_mcp_latest_launcher_1.ensureFraimMcpLatestLauncher)();
|
|
39
|
+
return {
|
|
40
|
+
command: launcher.command,
|
|
41
|
+
args: launcher.args,
|
|
42
|
+
env: {
|
|
43
|
+
// Include API key for IDE configs (Codex, VSCode, etc.)
|
|
44
|
+
// The stdio-server will use this if set, otherwise falls back to ~/.fraim/config.json
|
|
45
|
+
FRAIM_API_KEY: fraimKey,
|
|
46
|
+
FRAIM_REMOTE_URL: 'https://fraim.wellnessatwork.me'
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// PROVIDER MCP SERVER BUILDER (uses provider registry)
|
|
54
|
+
// ============================================================================
|
|
55
|
+
/**
|
|
56
|
+
* Build an MCP server for a provider using its definition from the registry
|
|
57
|
+
*/
|
|
58
|
+
async function buildProviderMCPServer(providerId, token, config) {
|
|
59
|
+
// Get provider definition from registry (server or local fallback)
|
|
60
|
+
const provider = await (0, provider_registry_1.getProvider)(providerId);
|
|
61
|
+
if (!provider) {
|
|
62
|
+
throw new Error(`Unknown provider: ${providerId}`);
|
|
63
|
+
}
|
|
64
|
+
if (!provider.mcpServer) {
|
|
65
|
+
throw new Error(`Provider ${providerId} does not have an MCP server configuration`);
|
|
66
|
+
}
|
|
67
|
+
const mcpConfig = provider.mcpServer;
|
|
68
|
+
// Validate config if provider requires additional config
|
|
69
|
+
if (provider.hasAdditionalConfig) {
|
|
70
|
+
const validation = await (0, provider_registry_1.validateProviderConfig)(providerId, config || {});
|
|
71
|
+
if (!validation.valid) {
|
|
72
|
+
throw new Error(`${provider.displayName} requires additional configuration: ${validation.missing.join(', ')}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Build MCP server based on type
|
|
76
|
+
if (mcpConfig.type === 'http') {
|
|
77
|
+
return buildHTTPServer(mcpConfig, token);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return buildStdioServer(mcpConfig, token, config);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build an HTTP MCP server.
|
|
85
|
+
* When authHeaderTemplate is absent the provider uses IDE-native OAuth (e.g. GitHub);
|
|
86
|
+
* write a URL-only entry so the IDE handles the OAuth flow on first tool use.
|
|
87
|
+
*/
|
|
88
|
+
function buildHTTPServer(mcpConfig, token) {
|
|
89
|
+
if (!mcpConfig.url) {
|
|
90
|
+
throw new Error('HTTP MCP server requires url');
|
|
91
|
+
}
|
|
92
|
+
if (!mcpConfig.authHeaderTemplate) {
|
|
93
|
+
return {
|
|
94
|
+
type: 'http',
|
|
95
|
+
url: mcpConfig.url
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
type: 'http',
|
|
100
|
+
url: mcpConfig.url,
|
|
101
|
+
headers: {
|
|
102
|
+
Authorization: mcpConfig.authHeaderTemplate.replace('{token}', token)
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Build a stdio MCP server
|
|
108
|
+
*/
|
|
109
|
+
function buildStdioServer(mcpConfig, token, config) {
|
|
110
|
+
if (!mcpConfig.command) {
|
|
111
|
+
throw new Error('Stdio MCP server requires command');
|
|
112
|
+
}
|
|
113
|
+
const resolveTemplate = (template) => {
|
|
114
|
+
let value = template.replace('{token}', token);
|
|
115
|
+
if (config) {
|
|
116
|
+
for (const [configKey, configValue] of Object.entries(config)) {
|
|
117
|
+
value = value.replace(`{config.${configKey}}`, String(configValue));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return value;
|
|
121
|
+
};
|
|
122
|
+
// Build environment variables from template
|
|
123
|
+
const env = {};
|
|
124
|
+
if (mcpConfig.envTemplate) {
|
|
125
|
+
for (const [key, template] of Object.entries(mcpConfig.envTemplate)) {
|
|
126
|
+
let value = resolveTemplate(template);
|
|
127
|
+
// Handle URL normalization for Jira
|
|
128
|
+
if (key === 'JIRA_URL' && value && !value.startsWith('http')) {
|
|
129
|
+
value = `https://${value}`;
|
|
130
|
+
}
|
|
131
|
+
env[key] = value;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
command: (0, command_resolution_1.resolveManagedCommand)(mcpConfig.command),
|
|
136
|
+
args: (mcpConfig.args || []).map(resolveTemplate),
|
|
137
|
+
env
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// REGISTRY LOOKUP FUNCTIONS
|
|
142
|
+
// ============================================================================
|
|
143
|
+
function getBaseMCPServer(id) {
|
|
144
|
+
return exports.BASE_MCP_SERVERS.find(server => server.id === id);
|
|
145
|
+
}
|
|
146
|
+
async function getProviderMCPServerIds() {
|
|
147
|
+
// This would need to fetch all providers and filter those with MCP servers
|
|
148
|
+
// For now, return empty array - this function is not critical
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
function getAllMCPServerIds() {
|
|
152
|
+
// Return only base server IDs
|
|
153
|
+
// Provider server IDs are dynamic and come from the registry
|
|
154
|
+
return exports.BASE_MCP_SERVERS.map(s => s.id);
|
|
155
|
+
}
|
|
156
|
+
async function isProviderServer(serverId) {
|
|
157
|
+
const provider = await (0, provider_registry_1.getProvider)(serverId);
|
|
158
|
+
return provider !== undefined && provider.mcpServer !== undefined;
|
|
159
|
+
}
|
|
160
|
+
async function isHTTPServer(serverId) {
|
|
161
|
+
const provider = await (0, provider_registry_1.getProvider)(serverId);
|
|
162
|
+
return provider?.mcpServer?.type === 'http';
|
|
163
|
+
}
|
|
164
|
+
// ============================================================================
|
|
165
|
+
// BUILDER HELPERS
|
|
166
|
+
// ============================================================================
|
|
167
|
+
function buildAllBaseServers(fraimKey) {
|
|
168
|
+
const servers = new Map();
|
|
169
|
+
for (const def of exports.BASE_MCP_SERVERS) {
|
|
170
|
+
servers.set(def.id, def.buildServer(fraimKey));
|
|
171
|
+
}
|
|
172
|
+
return servers;
|
|
173
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
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: 'Run "fraim add-provider github" — your IDE handles OAuth automatically on first use',
|
|
26
|
+
hasAdditionalConfig: false,
|
|
27
|
+
mcpServer: {
|
|
28
|
+
type: 'http',
|
|
29
|
+
url: 'https://api.githubcopilot.com/mcp/'
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: 'gitlab',
|
|
34
|
+
displayName: 'GitLab',
|
|
35
|
+
description: 'GitLab repository and issue management',
|
|
36
|
+
capabilities: ['code', 'issues', 'integrated'],
|
|
37
|
+
docsUrl: 'https://docs.gitlab.com',
|
|
38
|
+
setupInstructions: 'Create a Personal Access Token in your GitLab settings',
|
|
39
|
+
hasAdditionalConfig: false,
|
|
40
|
+
mcpServer: {
|
|
41
|
+
type: 'http',
|
|
42
|
+
url: 'https://gitlab.com/api/v4/mcp',
|
|
43
|
+
authHeaderTemplate: 'Bearer {token}'
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'ado',
|
|
48
|
+
displayName: 'Azure DevOps',
|
|
49
|
+
description: 'Azure DevOps repository and issue management',
|
|
50
|
+
capabilities: ['code', 'issues', 'integrated'],
|
|
51
|
+
docsUrl: 'https://docs.microsoft.com/azure/devops',
|
|
52
|
+
setupInstructions: 'Create a Personal Access Token in Azure DevOps',
|
|
53
|
+
hasAdditionalConfig: true,
|
|
54
|
+
mcpServer: {
|
|
55
|
+
type: 'stdio',
|
|
56
|
+
command: 'npx',
|
|
57
|
+
args: ['-y', '@azure-devops/mcp', '{config.organization}', '--authentication', 'envvar'],
|
|
58
|
+
envTemplate: {
|
|
59
|
+
ADO_MCP_AUTH_TOKEN: '{token}'
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'jira',
|
|
65
|
+
displayName: 'Jira',
|
|
66
|
+
description: 'Jira issue tracking and project management',
|
|
67
|
+
capabilities: ['issues'],
|
|
68
|
+
docsUrl: 'https://support.atlassian.com/jira',
|
|
69
|
+
setupInstructions: 'Create an API token at https://id.atlassian.com/manage-profile/security/api-tokens',
|
|
70
|
+
hasAdditionalConfig: true,
|
|
71
|
+
mcpServer: {
|
|
72
|
+
type: 'stdio',
|
|
73
|
+
command: 'uvx',
|
|
74
|
+
args: ['mcp-atlassian'],
|
|
75
|
+
envTemplate: {
|
|
76
|
+
JIRA_URL: '{config.baseUrl}',
|
|
77
|
+
JIRA_USERNAME: '{config.email}',
|
|
78
|
+
JIRA_API_TOKEN: '{token}'
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
];
|
|
83
|
+
const ADO_CONFIG_REQUIREMENTS = [
|
|
84
|
+
{
|
|
85
|
+
key: 'organization',
|
|
86
|
+
displayName: 'Azure DevOps Organization',
|
|
87
|
+
description: 'Your Azure DevOps organization name (e.g., contoso)',
|
|
88
|
+
required: true,
|
|
89
|
+
type: 'string',
|
|
90
|
+
cliOptionName: 'organization'
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
const JIRA_CONFIG_REQUIREMENTS = [
|
|
94
|
+
{
|
|
95
|
+
key: 'baseUrl',
|
|
96
|
+
displayName: 'Jira Instance URL',
|
|
97
|
+
description: 'Your Jira instance URL (e.g., mycompany.atlassian.net)',
|
|
98
|
+
required: true,
|
|
99
|
+
type: 'url',
|
|
100
|
+
cliOptionName: 'url'
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
key: 'email',
|
|
104
|
+
displayName: 'Email Address',
|
|
105
|
+
description: 'Your Jira account email address',
|
|
106
|
+
required: true,
|
|
107
|
+
type: 'email'
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
function getLocalProvider(id) {
|
|
111
|
+
return LOCAL_PROVIDERS.find(p => p.id === id);
|
|
112
|
+
}
|
|
113
|
+
function getAllLocalProviders() {
|
|
114
|
+
return [...LOCAL_PROVIDERS];
|
|
115
|
+
}
|
|
116
|
+
function getAllLocalProviderIds() {
|
|
117
|
+
return LOCAL_PROVIDERS.map(p => p.id);
|
|
118
|
+
}
|
|
119
|
+
function isValidLocalProviderId(id) {
|
|
120
|
+
return LOCAL_PROVIDERS.some(p => p.id === id);
|
|
121
|
+
}
|
|
122
|
+
function getLocalProviderDisplayName(providerId) {
|
|
123
|
+
const provider = getLocalProvider(providerId);
|
|
124
|
+
return provider?.displayName || providerId;
|
|
125
|
+
}
|
|
126
|
+
function getLocalProviderSetupInstructions(providerId) {
|
|
127
|
+
const provider = getLocalProvider(providerId);
|
|
128
|
+
return provider?.setupInstructions || '';
|
|
129
|
+
}
|
|
130
|
+
function getLocalProviderConfigRequirements(providerId) {
|
|
131
|
+
if (providerId === 'ado') {
|
|
132
|
+
return ADO_CONFIG_REQUIREMENTS;
|
|
133
|
+
}
|
|
134
|
+
if (providerId === 'jira') {
|
|
135
|
+
return JIRA_CONFIG_REQUIREMENTS;
|
|
136
|
+
}
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
function localRequiresAdditionalConfig(providerId) {
|
|
140
|
+
return getLocalProviderConfigRequirements(providerId).length > 0;
|
|
141
|
+
}
|
|
142
|
+
function validateLocalProviderConfig(providerId, config) {
|
|
143
|
+
const requirements = getLocalProviderConfigRequirements(providerId);
|
|
144
|
+
const missing = [];
|
|
145
|
+
for (const req of requirements) {
|
|
146
|
+
if (req.required && !config[req.key]) {
|
|
147
|
+
missing.push(req.key);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
valid: missing.length === 0,
|
|
152
|
+
missing
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function getLocalProvidersWithCapability(capability) {
|
|
156
|
+
return LOCAL_PROVIDERS.filter(provider => provider.capabilities.includes(capability));
|
|
157
|
+
}
|
|
158
|
+
function getLocalProviderIdsWithCapability(capability) {
|
|
159
|
+
const providers = getLocalProvidersWithCapability(capability);
|
|
160
|
+
return providers.map(p => p.id);
|
|
161
|
+
}
|
|
162
|
+
function localProviderHasCapability(providerId, capability) {
|
|
163
|
+
const provider = getLocalProvider(providerId);
|
|
164
|
+
return provider ? provider.capabilities.includes(capability) : false;
|
|
165
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configures Claude Code user-level settings for FRAIM token telemetry.
|
|
4
|
+
*
|
|
5
|
+
* Writes OTel env vars to ~/.claude/settings.json so ALL Claude Code
|
|
6
|
+
* sessions push metrics to the FRAIM local proxy's OTLP receiver.
|
|
7
|
+
* User-level so it works across all projects without per-project setup.
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.ensureClaudeCodeTelemetryEnv = ensureClaudeCodeTelemetryEnv;
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const os_1 = __importDefault(require("os"));
|
|
17
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
18
|
+
const TELEMETRY_ENV = {
|
|
19
|
+
CLAUDE_CODE_ENABLE_TELEMETRY: '1',
|
|
20
|
+
OTEL_METRICS_EXPORTER: 'otlp',
|
|
21
|
+
OTEL_EXPORTER_OTLP_PROTOCOL: 'http/json',
|
|
22
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: 'http://localhost:4318',
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Ensure Claude Code user-level settings include OTel env vars for token telemetry.
|
|
26
|
+
* Writes to ~/.claude/settings.json. Merges without overwriting user-set values.
|
|
27
|
+
*/
|
|
28
|
+
function ensureClaudeCodeTelemetryEnv() {
|
|
29
|
+
const settingsDir = path_1.default.join(os_1.default.homedir(), '.claude');
|
|
30
|
+
const settingsPath = path_1.default.join(settingsDir, 'settings.json');
|
|
31
|
+
let settings = {};
|
|
32
|
+
if (fs_1.default.existsSync(settingsPath)) {
|
|
33
|
+
try {
|
|
34
|
+
settings = JSON.parse(fs_1.default.readFileSync(settingsPath, 'utf8'));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Corrupt file — will overwrite
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (!fs_1.default.existsSync(settingsDir)) {
|
|
41
|
+
fs_1.default.mkdirSync(settingsDir, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
const existingEnv = settings.env || {};
|
|
44
|
+
let added = 0;
|
|
45
|
+
for (const [key, value] of Object.entries(TELEMETRY_ENV)) {
|
|
46
|
+
if (!(key in existingEnv)) {
|
|
47
|
+
existingEnv[key] = value;
|
|
48
|
+
added++;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (added > 0) {
|
|
52
|
+
settings.env = existingEnv;
|
|
53
|
+
fs_1.default.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
54
|
+
console.log(chalk_1.default.green(` ✅ Enabled token telemetry in ~/.claude/settings.json (${added} env vars)`));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.log(chalk_1.default.gray(` ⏭️ Token telemetry already configured in ~/.claude/settings.json`));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ensureCodexLocalConfig = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const mcp_config_generator_1 = require("./mcp-config-generator");
|
|
10
|
+
const escapeTomlString = (value) => value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
11
|
+
const buildFraimCwdBlock = (projectRoot) => `
|
|
12
|
+
[mcp_servers.fraim]
|
|
13
|
+
cwd = "${escapeTomlString(projectRoot)}"
|
|
14
|
+
`;
|
|
15
|
+
const ensureCodexLocalConfig = (projectRoot) => {
|
|
16
|
+
const codexDir = path_1.default.join(projectRoot, '.codex');
|
|
17
|
+
const codexConfigPath = path_1.default.join(codexDir, 'config.toml');
|
|
18
|
+
if (!fs_1.default.existsSync(codexDir)) {
|
|
19
|
+
fs_1.default.mkdirSync(codexDir, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
const hadExistingFile = fs_1.default.existsSync(codexConfigPath);
|
|
22
|
+
const existingContent = hadExistingFile ? fs_1.default.readFileSync(codexConfigPath, 'utf8') : '';
|
|
23
|
+
const generatedContent = buildFraimCwdBlock(projectRoot);
|
|
24
|
+
const mergeResult = (0, mcp_config_generator_1.mergeTomlMCPServers)(existingContent, generatedContent, ['fraim']);
|
|
25
|
+
const normalizedExisting = existingContent.replace(/\r\n/g, '\n');
|
|
26
|
+
const normalizedMerged = mergeResult.content.replace(/\r\n/g, '\n');
|
|
27
|
+
const shouldWrite = !hadExistingFile || normalizedExisting !== normalizedMerged;
|
|
28
|
+
if (shouldWrite) {
|
|
29
|
+
fs_1.default.writeFileSync(codexConfigPath, mergeResult.content);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
path: codexConfigPath,
|
|
33
|
+
created: !hadExistingFile,
|
|
34
|
+
updated: shouldWrite && hadExistingFile
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
exports.ensureCodexLocalConfig = ensureCodexLocalConfig;
|