fraim-framework 2.0.177 → 2.0.180
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/dist/src/ai-hub/desktop-main.js +2 -2
- package/dist/src/ai-hub/server.js +50 -1
- 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/personas/me.js +29 -0
- package/dist/src/api/pricing/get-config.js +25 -0
- package/dist/src/api/sales/contact.js +44 -0
- package/dist/src/cli/commands/add-provider.js +74 -61
- package/dist/src/cli/commands/add-surface.js +128 -0
- package/dist/src/cli/commands/login.js +5 -69
- package/dist/src/cli/commands/setup.js +27 -347
- package/dist/src/cli/distribution/marketplace-bundles.js +580 -0
- package/dist/src/cli/fraim.js +2 -0
- package/dist/src/cli/mcp/ide-formats.js +5 -3
- package/dist/src/cli/mcp/mcp-server-registry.js +10 -3
- package/dist/src/cli/providers/local-provider-registry.js +2 -3
- package/dist/src/cli/setup/auto-mcp-setup.js +9 -32
- package/dist/src/cli/setup/ide-detector.js +34 -14
- package/dist/src/config/persona-capability-bundles.js +17 -13
- package/dist/src/db/payment-repository.js +61 -0
- package/dist/src/first-run/session-service.js +2 -2
- package/dist/src/fraim/config-loader.js +11 -0
- package/dist/src/fraim/db-service.js +2387 -0
- package/dist/src/fraim/issues.js +152 -0
- package/dist/src/fraim/template-processor.js +184 -0
- package/dist/src/fraim/utils/request-utils.js +23 -0
- package/dist/src/local-mcp-server/stdio-server.js +28 -4
- package/dist/src/local-mcp-server/usage-collector.js +24 -0
- package/dist/src/middleware/auth.js +266 -0
- package/dist/src/middleware/cors-config.js +111 -0
- package/dist/src/middleware/logger.js +116 -0
- package/dist/src/middleware/rate-limit.js +110 -0
- package/dist/src/middleware/reject-query-api-key.js +45 -0
- package/dist/src/middleware/security-headers.js +41 -0
- package/dist/src/middleware/telemetry.js +134 -0
- package/dist/src/models/payment.js +2 -0
- package/dist/src/routes/analytics.js +1447 -0
- package/dist/src/routes/app-routes.js +32 -0
- package/dist/src/routes/auth-routes.js +505 -0
- package/dist/src/routes/oauth-routes.js +325 -0
- package/dist/src/routes/payment-routes.js +186 -0
- package/dist/src/routes/persona-catalog-routes.js +84 -0
- package/dist/src/services/admin-service.js +229 -0
- package/dist/src/services/audit-log-persistence.js +60 -0
- package/dist/src/services/audit-log.js +69 -0
- package/dist/src/services/cookie-service.js +129 -0
- package/dist/src/services/dashboard-access.js +27 -0
- package/dist/src/services/demo-seed-service.js +139 -0
- package/dist/src/services/email-code.js +23 -0
- package/dist/src/services/email-service-clean.js +782 -0
- package/dist/src/services/email-service.js +951 -0
- package/dist/src/services/installer-service.js +131 -0
- package/dist/src/services/mcp-oauth-store.js +33 -0
- package/dist/src/services/mcp-service.js +823 -0
- package/dist/src/services/oauth-helpers.js +127 -0
- package/dist/src/services/org-service.js +89 -0
- package/dist/src/services/persona-entitlement-service.js +288 -0
- package/dist/src/services/provider-service.js +215 -0
- package/dist/src/services/registry-service.js +628 -0
- package/dist/src/services/session-service.js +86 -0
- package/dist/src/services/trial-reminder-service.js +120 -0
- package/dist/src/services/usage-analytics-service.js +419 -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/package.json +14 -3
- package/public/ai-hub/index.html +14 -2
- package/public/ai-hub/script.js +340 -66
- package/public/ai-hub/styles.css +83 -0
|
@@ -44,17 +44,7 @@ const prompts_1 = __importDefault(require("prompts"));
|
|
|
44
44
|
const ide_detector_1 = require("./ide-detector");
|
|
45
45
|
const mcp_config_generator_1 = require("./mcp-config-generator");
|
|
46
46
|
const codex_local_config_1 = require("./codex-local-config");
|
|
47
|
-
const
|
|
48
|
-
const normalizePlatformTokens = (tokenInput) => {
|
|
49
|
-
if (!tokenInput)
|
|
50
|
-
return {};
|
|
51
|
-
if (typeof tokenInput === 'string') {
|
|
52
|
-
return tokenInput ? { github: tokenInput } : {};
|
|
53
|
-
}
|
|
54
|
-
return tokenInput;
|
|
55
|
-
};
|
|
56
|
-
const promptForIDESelection = async (detectedIDEs, tokenInput) => {
|
|
57
|
-
const tokens = normalizePlatformTokens(tokenInput);
|
|
47
|
+
const promptForIDESelection = async (detectedIDEs) => {
|
|
58
48
|
if (process.env.FRAIM_NON_INTERACTIVE) {
|
|
59
49
|
console.log(chalk_1.default.yellow(`\nℹ️ Non-interactive mode: configuring all detected IDEs (${detectedIDEs.length})`));
|
|
60
50
|
return detectedIDEs;
|
|
@@ -70,17 +60,8 @@ const promptForIDESelection = async (detectedIDEs, tokenInput) => {
|
|
|
70
60
|
console.log(chalk_1.default.blue('FRAIM will add these MCP servers to selected IDEs:'));
|
|
71
61
|
console.log(chalk_1.default.gray(' • fraim (required for FRAIM jobs)'));
|
|
72
62
|
console.log(chalk_1.default.gray(' • git (version control integration)'));
|
|
73
|
-
// Show configured provider MCP servers dynamically
|
|
74
|
-
const allProviderIds = await (0, provider_registry_1.getAllProviderIds)();
|
|
75
|
-
for (const providerId of allProviderIds) {
|
|
76
|
-
if (tokens[providerId]) {
|
|
77
|
-
const provider = await (0, provider_registry_1.getProvider)(providerId);
|
|
78
|
-
if (provider) {
|
|
79
|
-
console.log(chalk_1.default.gray(` - ${providerId} (${provider.displayName} API access)`));
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
63
|
console.log(chalk_1.default.gray(' • playwright (browser automation)'));
|
|
64
|
+
console.log(chalk_1.default.blue('\n💡 Run "fraim add-provider <provider>" after setup to connect GitHub, GitLab, Jira, or other tools.'));
|
|
84
65
|
console.log(chalk_1.default.yellow('\n💡 Existing MCP servers will be preserved - only missing servers will be added.'));
|
|
85
66
|
const response = await (0, prompts_1.default)({
|
|
86
67
|
type: 'text',
|
|
@@ -153,8 +134,7 @@ const validateSetupResults = async (configuredIDEs) => {
|
|
|
153
134
|
}
|
|
154
135
|
};
|
|
155
136
|
exports.validateSetupResults = validateSetupResults;
|
|
156
|
-
const configureIDEMCP = async (ide, fraimKey
|
|
157
|
-
const tokens = normalizePlatformTokens(tokenInput);
|
|
137
|
+
const configureIDEMCP = async (ide, fraimKey) => {
|
|
158
138
|
const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
|
|
159
139
|
console.log(chalk_1.default.blue(`🔧 Configuring ${ide.name}...`));
|
|
160
140
|
// Create backup
|
|
@@ -185,11 +165,9 @@ const configureIDEMCP = async (ide, fraimKey, tokenInput, providerConfigs) => {
|
|
|
185
165
|
existingTomlContent = fs_1.default.readFileSync(configPath, 'utf8');
|
|
186
166
|
console.log(chalk_1.default.gray(` 📋 Found existing TOML config`));
|
|
187
167
|
}
|
|
188
|
-
const newTomlContent = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey,
|
|
168
|
+
const newTomlContent = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, {});
|
|
189
169
|
const { getAllMCPServerIds } = await Promise.resolve().then(() => __importStar(require('../mcp/mcp-server-registry')));
|
|
190
|
-
const
|
|
191
|
-
const providerServerIds = Object.keys(tokens).filter(id => tokens[id]);
|
|
192
|
-
const serversToAdd = [...baseServerIds, ...providerServerIds];
|
|
170
|
+
const serversToAdd = getAllMCPServerIds();
|
|
193
171
|
const mergeResult = (0, mcp_config_generator_1.mergeTomlMCPServers)(existingTomlContent, newTomlContent, serversToAdd);
|
|
194
172
|
fs_1.default.writeFileSync(configPath, mergeResult.content);
|
|
195
173
|
mergeResult.addedServers.forEach(server => {
|
|
@@ -204,7 +182,7 @@ const configureIDEMCP = async (ide, fraimKey, tokenInput, providerConfigs) => {
|
|
|
204
182
|
}
|
|
205
183
|
else {
|
|
206
184
|
// For JSON configs - intelligent merging
|
|
207
|
-
const newConfig = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey,
|
|
185
|
+
const newConfig = await (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, {});
|
|
208
186
|
const newMCPServers = newConfig[serversKey] || newConfig.mcpServers || {};
|
|
209
187
|
// Merge MCP servers intelligently
|
|
210
188
|
const mergedMCPServers = { ...existingMCPServers };
|
|
@@ -251,8 +229,7 @@ const configureIDEMCP = async (ide, fraimKey, tokenInput, providerConfigs) => {
|
|
|
251
229
|
console.log(chalk_1.default.green(` ✅ ${status} local Codex config: ${localResult.path}`));
|
|
252
230
|
}
|
|
253
231
|
};
|
|
254
|
-
const autoConfigureMCP = async (fraimKey,
|
|
255
|
-
const tokens = normalizePlatformTokens(tokenInput);
|
|
232
|
+
const autoConfigureMCP = async (fraimKey, selectedIDEs) => {
|
|
256
233
|
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
257
234
|
if (detectedIDEs.length === 0 && (!selectedIDEs || selectedIDEs.length === 0)) {
|
|
258
235
|
console.log(chalk_1.default.yellow('⚠️ No supported IDEs detected.'));
|
|
@@ -294,7 +271,7 @@ const autoConfigureMCP = async (fraimKey, tokenInput, selectedIDEs, providerConf
|
|
|
294
271
|
}
|
|
295
272
|
else {
|
|
296
273
|
// Interactive selection
|
|
297
|
-
idesToConfigure = await (0, exports.promptForIDESelection)(detectedIDEs
|
|
274
|
+
idesToConfigure = await (0, exports.promptForIDESelection)(detectedIDEs);
|
|
298
275
|
}
|
|
299
276
|
if (idesToConfigure.length === 0) {
|
|
300
277
|
console.log(chalk_1.default.yellow('⚠️ No IDEs selected for configuration.'));
|
|
@@ -308,7 +285,7 @@ const autoConfigureMCP = async (fraimKey, tokenInput, selectedIDEs, providerConf
|
|
|
308
285
|
};
|
|
309
286
|
for (const ide of idesToConfigure) {
|
|
310
287
|
try {
|
|
311
|
-
await configureIDEMCP(ide, fraimKey
|
|
288
|
+
await configureIDEMCP(ide, fraimKey);
|
|
312
289
|
results.successful.push(ide.name);
|
|
313
290
|
}
|
|
314
291
|
catch (error) {
|
|
@@ -24,15 +24,25 @@ const checkMultiplePaths = (paths) => {
|
|
|
24
24
|
return paths.some(p => fs_1.default.existsSync(expandPath(p)));
|
|
25
25
|
};
|
|
26
26
|
// Issue #646 (Bug 2): a config directory left behind after uninstall (e.g. ~/.cursor,
|
|
27
|
-
// ~/Library/Application Support/Cursor) made config-surface detection report
|
|
28
|
-
// as "Installed" when it was not.
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
const macAppBundlePaths = (appName) => [
|
|
27
|
+
// ~/Library/Application Support/Cursor) made config-surface detection report Cursor
|
|
28
|
+
// as "Installed" when it was not. App evidence is the reliable signal for Cursor;
|
|
29
|
+
// other GUI surfaces keep their existing config-surface checks for compatibility
|
|
30
|
+
// with the #640 first-run detection contract.
|
|
31
|
+
const appBundlePaths = (appName) => [
|
|
33
32
|
`/Applications/${appName}.app`,
|
|
34
33
|
`~/Applications/${appName}.app`,
|
|
35
34
|
];
|
|
35
|
+
const windowsUserAppPaths = (appName) => {
|
|
36
|
+
switch (appName) {
|
|
37
|
+
case 'Cursor':
|
|
38
|
+
return [
|
|
39
|
+
'~/AppData/Local/Programs/Cursor/Cursor.exe',
|
|
40
|
+
'~/AppData/Local/Cursor/Cursor.exe',
|
|
41
|
+
];
|
|
42
|
+
default:
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
};
|
|
36
46
|
// Issue #646 follow-up: a user may run a GUI app from a non-standard location
|
|
37
47
|
// (e.g. straight from a mounted DMG: /Volumes/.../Cursor.app) that the
|
|
38
48
|
// /Applications checks miss. A running process of the app is definitive proof it
|
|
@@ -48,10 +58,19 @@ const isMacAppRunning = (appName) => {
|
|
|
48
58
|
const result = (0, child_process_1.spawnSync)('pgrep', ['-f', `${appName}.app/Contents`], { encoding: 'utf8', timeout: 1500 });
|
|
49
59
|
return result.status === 0 && Boolean((result.stdout || '').trim());
|
|
50
60
|
};
|
|
51
|
-
const
|
|
61
|
+
const hasAppEvidence = (appName) => {
|
|
62
|
+
const evidencePaths = process.platform === 'win32'
|
|
63
|
+
? [...appBundlePaths(appName), ...windowsUserAppPaths(appName)]
|
|
64
|
+
: appBundlePaths(appName);
|
|
65
|
+
return checkMultiplePaths(evidencePaths) || isMacAppRunning(appName);
|
|
66
|
+
};
|
|
67
|
+
const guiAppDetect = (configSurfaceCheck, appName, options = {}) => {
|
|
52
68
|
return () => {
|
|
69
|
+
if (options.requireAppEvidence) {
|
|
70
|
+
return hasAppEvidence(appName);
|
|
71
|
+
}
|
|
53
72
|
if (process.platform === 'darwin') {
|
|
54
|
-
return
|
|
73
|
+
return hasAppEvidence(appName);
|
|
55
74
|
}
|
|
56
75
|
return configSurfaceCheck();
|
|
57
76
|
};
|
|
@@ -81,12 +100,12 @@ const detectVSCode = () => {
|
|
|
81
100
|
];
|
|
82
101
|
return checkMultiplePaths(paths);
|
|
83
102
|
};
|
|
84
|
-
const
|
|
103
|
+
const detectCursorMcpConfig = () => {
|
|
85
104
|
const paths = [
|
|
86
|
-
'~/.cursor',
|
|
87
|
-
'~/Library/Application Support/Cursor',
|
|
88
|
-
'~/AppData/Roaming/Cursor',
|
|
89
|
-
'~/.config/Cursor'
|
|
105
|
+
'~/.cursor/mcp.json',
|
|
106
|
+
'~/Library/Application Support/Cursor/mcp.json',
|
|
107
|
+
'~/AppData/Roaming/Cursor/mcp.json',
|
|
108
|
+
'~/.config/Cursor/mcp.json'
|
|
90
109
|
];
|
|
91
110
|
return checkMultiplePaths(paths);
|
|
92
111
|
};
|
|
@@ -104,6 +123,7 @@ const detectGeminiCli = () => {
|
|
|
104
123
|
};
|
|
105
124
|
const detectGeminiSurface = () => {
|
|
106
125
|
const paths = [
|
|
126
|
+
'~/.gemini',
|
|
107
127
|
'~/.gemini/settings.json',
|
|
108
128
|
'~/AppData/Roaming/gemini/settings.json',
|
|
109
129
|
'~/.config/gemini/settings.json'
|
|
@@ -196,7 +216,7 @@ exports.IDE_CONFIGS = [
|
|
|
196
216
|
configType: 'kiro',
|
|
197
217
|
adapterConfigType: 'cursor',
|
|
198
218
|
invocationProfile: 'cursor-mention',
|
|
199
|
-
detectMethod:
|
|
219
|
+
detectMethod: () => detectCursorMcpConfig() || hasAppEvidence('Cursor'),
|
|
200
220
|
alternativePaths: [
|
|
201
221
|
'~/Library/Application Support/Cursor/mcp.json',
|
|
202
222
|
'~/AppData/Roaming/Cursor/mcp.json',
|
|
@@ -40,7 +40,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
40
40
|
personaKey: 'beza',
|
|
41
41
|
bundleId: 'persona-beza-core',
|
|
42
42
|
catalogMetadata: buildCatalogMetadata('beza', ['competitive-analysis', 'review-business-strategy', 'business-plan-creation']),
|
|
43
|
-
protectedJobs: ['competitive-analysis', 'review-business-strategy', 'business-plan-creation', 'problem-statement-crystallization', 'business-idea-validation-and-scoping', 'founder-market-fit-analysis', '
|
|
43
|
+
protectedJobs: ['competitive-analysis', 'review-business-strategy', 'business-plan-creation', 'problem-statement-crystallization', 'business-idea-validation-and-scoping', 'founder-market-fit-analysis', 'community-funding-preparation', 'fundraising-prospect-discovery', 'investor-pitch-preparation', 'review-funding-preparation', 'advisory-board-development', 'advisor-interview', 'advisory-board-selection', 'blue-sky-brainstorming', 'domain-registration-research'],
|
|
44
44
|
protectedAliases: ['business-strategy', 'company-strategy'],
|
|
45
45
|
defaultHireMode: 'job',
|
|
46
46
|
lockCopy: 'Hire BeZa to unlock business strategy work for this request.'
|
|
@@ -49,7 +49,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
49
49
|
personaKey: 'pam',
|
|
50
50
|
bundleId: 'persona-pam-core',
|
|
51
51
|
catalogMetadata: buildCatalogMetadata('pam', ['feature-specification', 'technical-design', 'issue-preparation']),
|
|
52
|
-
protectedJobs: ['feature-specification', 'technical-design', 'issue-preparation', 'implementation-design-review', 'issue-retrospective', 'work-completion', 'scrum-sprint-planning', 'mvp-validation-plan'],
|
|
52
|
+
protectedJobs: ['feature-specification', 'technical-design', 'issue-preparation', 'implementation-design-review', 'issue-retrospective', 'work-completion', 'scrum-sprint-planning', 'mvp-validation-plan', 'sprint-planning', 'customer-prospect-discovery', 'interview-preparation', 'participant-recruitment', 'process-interview-notes', 'review-customer-development', 'triage-customer-needs'],
|
|
53
53
|
protectedAliases: ['product-management', 'product-spec'],
|
|
54
54
|
defaultHireMode: 'job',
|
|
55
55
|
lockCopy: 'Hire PaM to unlock product-management work for this request.'
|
|
@@ -58,7 +58,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
58
58
|
personaKey: 'swen',
|
|
59
59
|
bundleId: 'persona-swen-core',
|
|
60
60
|
catalogMetadata: buildCatalogMetadata('swen', ['feature-implementation', 'code-refactoring', 'pr-iteration']),
|
|
61
|
-
protectedJobs: ['feature-implementation', 'code-refactoring', 'pr-iteration', 'mobile-app-development', 'mcp-server-creation', 'cloud-application-deployment', 'cloud-cost-optimization', 'cloud-performance-diagnosis', 'route-llm-spend-to-cloud-credits', 'set-up-cloud-cost-alerts', 'gitlabs-to-github', 'system-migration', 'cross-cloud-migration', 'data-pipeline-design', 'data-quality-monitoring', 'data-platform-architecture', 'write-dev-docs', 'database-schema-design'],
|
|
61
|
+
protectedJobs: ['feature-implementation', 'code-refactoring', 'pr-iteration', 'mobile-app-development', 'mcp-server-creation', 'cloud-application-deployment', 'cloud-cost-optimization', 'cloud-performance-diagnosis', 'route-llm-spend-to-cloud-credits', 'set-up-cloud-cost-alerts', 'gitlabs-to-github', 'system-migration', 'cross-cloud-migration', 'data-pipeline-design', 'data-quality-monitoring', 'data-platform-architecture', 'write-dev-docs', 'database-schema-design', 'create-architecture', 'project-scaffolding', 'codebase-analysis-and-ideation', 'github-org-setup', 'google-workspace-setup', 'mobile-app-rejection-response', 'mobile-app-submission', 'publish-mcp-app', 'application-replication-workflow'],
|
|
62
62
|
protectedAliases: ['software-engineering', 'implementation'],
|
|
63
63
|
defaultHireMode: 'job',
|
|
64
64
|
lockCopy: 'Hire SWEn to unlock software-engineering delivery for this request.'
|
|
@@ -76,7 +76,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
76
76
|
personaKey: 'huxley',
|
|
77
77
|
bundleId: 'persona-huxley-core',
|
|
78
78
|
catalogMetadata: buildCatalogMetadata('huxley', ['design-system-creation', 'user-facing-prototyping', 'ux-research-synthesis']),
|
|
79
|
-
protectedJobs: ['design-system-creation', 'user-facing-prototyping', 'website-creation', '
|
|
79
|
+
protectedJobs: ['design-system-creation', 'user-facing-prototyping', 'website-creation', 'brand-creation', 'branding-quality-audit', 'ux-research-synthesis', 'user-journey-mapping'],
|
|
80
80
|
protectedAliases: ['ux-design', 'brand-design'],
|
|
81
81
|
defaultHireMode: 'job',
|
|
82
82
|
lockCopy: 'Hire hUXley to unlock design-system, UX research, and brand design work for this request.'
|
|
@@ -85,7 +85,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
85
85
|
personaKey: 'gautam',
|
|
86
86
|
bundleId: 'persona-gautam-core',
|
|
87
87
|
catalogMetadata: buildCatalogMetadata('gautam', ['analyze-revenue-system', 'build-gtm-motion', 'ppc-campaign-management']),
|
|
88
|
-
protectedJobs: ['pricing-strategy-definition', 'marketing-strategy-definition', 'product-launch-management', '
|
|
88
|
+
protectedJobs: ['pricing-strategy-definition', 'marketing-strategy-definition', 'product-launch-management', 'evangelist-content-development', 'funnel-analysis', 'growth-loop-design', 'analyze-revenue-system', 'design-gtm-system', 'build-gtm-motion', 'build-gtm-stack', 'plan-gtm-team', 'marketing-content-creation', 'ppc-campaign-management', 'paid-social-strategy', 'ad-performance-analysis', 'tracking-and-attribution-setup', 'developer-advocacy', 'seo-strategy', 'marketing-analytics-review', 'linkedin-company-page-setup', 'x-account-setup', 'social-engagement-campaign', 'thought-leadership-engagement', 'promo-video-creation', 'linkedin-carousel-from-deck'],
|
|
89
89
|
protectedAliases: ['gtm', 'marketing'],
|
|
90
90
|
defaultHireMode: 'job',
|
|
91
91
|
lockCopy: 'Hire GauTaM to unlock go-to-market and paid media work for this request.'
|
|
@@ -94,7 +94,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
94
94
|
personaKey: 'cela',
|
|
95
95
|
bundleId: 'persona-cela-core',
|
|
96
96
|
catalogMetadata: buildCatalogMetadata('cela', ['contract-review-analysis', 'nda-creation', 'saas-contract-package-creation']),
|
|
97
|
-
protectedJobs: ['contract-review-analysis', 'nda-creation', 'saas-contract-package-creation', 'trademark-registration-management', 'provisional-patent-application-creation', 'opensign-cloud-esign-dispatch', 'w9-creation', '
|
|
97
|
+
protectedJobs: ['contract-review-analysis', 'nda-creation', 'saas-contract-package-creation', 'trademark-registration-management', 'provisional-patent-application-creation', 'opensign-cloud-esign-dispatch', 'w9-creation', 'entity-type-selection', 'state-incorporation-filing', 'business-tax-registration', 'ein-application', 'cap-table-construction', 'founder-and-equity-agreements', 'ip-assignment-agreement-creation', 'employment-structure-decision'],
|
|
98
98
|
protectedAliases: ['legal', 'counsel'],
|
|
99
99
|
defaultHireMode: 'job',
|
|
100
100
|
lockCopy: 'Hire CELiA to unlock legal workflow support for this request.'
|
|
@@ -103,7 +103,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
103
103
|
personaKey: 'sekhar',
|
|
104
104
|
bundleId: 'persona-sekhar-core',
|
|
105
105
|
catalogMetadata: buildCatalogMetadata('sekhar', ['security-review', 'ai-native-security-setup', 'security-findings-command-center']),
|
|
106
|
-
protectedJobs: ['security-review', 'ai-native-security-setup', 'security-findings-command-center', 'vulnerability-triage-and-remediation', '
|
|
106
|
+
protectedJobs: ['security-review', 'ai-native-security-setup', 'security-findings-command-center', 'vulnerability-triage-and-remediation', 'compliance-review', 'compliance-continuous-monitoring', 'compliance-policy-authoring', 'compliance-questionnaire-response', 'compliance-requirements-detection', 'generate-audit-evidence', 'regulation-evidence-management', 'soc2-evidence-management'],
|
|
107
107
|
protectedAliases: ['security', 'appsec'],
|
|
108
108
|
defaultHireMode: 'job',
|
|
109
109
|
lockCopy: 'Hire SEChar to unlock security setup, review, and findings-command work for this request.'
|
|
@@ -112,7 +112,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
112
112
|
personaKey: 'ashley',
|
|
113
113
|
bundleId: 'persona-ashley-core',
|
|
114
114
|
catalogMetadata: buildCatalogMetadata('ashley', ['executive-assistant', 'weekly-operating-review', 'send-thank-you-notes']),
|
|
115
|
-
protectedJobs: ['executive-assistant', 'weekly-operating-review', 'send-thank-you-notes', 'send-newsletter', 'analyze-transcript', 'send-stakeholder-update'
|
|
115
|
+
protectedJobs: ['executive-assistant', 'weekly-operating-review', 'send-thank-you-notes', 'send-newsletter', 'analyze-transcript', 'send-stakeholder-update'],
|
|
116
116
|
protectedAliases: ['executive-assistant', 'operations-assistant'],
|
|
117
117
|
defaultHireMode: 'job',
|
|
118
118
|
lockCopy: 'Hire AshLey to unlock executive-assistant work for this request.'
|
|
@@ -121,7 +121,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
121
121
|
personaKey: 'mandy',
|
|
122
122
|
bundleId: 'persona-mandy-core',
|
|
123
123
|
catalogMetadata: buildCatalogMetadata('mandy', ['fully-delegate', 'project-plan-creation', 'stakeholder-status-reporting']),
|
|
124
|
-
protectedJobs: ['fully-delegate', 'delivery-governance-review', 'project-plan-creation', 'stakeholder-status-reporting', 'experiment-tracking', 'cross-functional-dependency-management'],
|
|
124
|
+
protectedJobs: ['fully-delegate', 'delivery-governance-review', 'project-plan-creation', 'stakeholder-status-reporting', 'experiment-tracking', 'cross-functional-dependency-management', 'portfolio-impact-report'],
|
|
125
125
|
protectedAliases: ['manager', 'team-lead', 'orchestrator'],
|
|
126
126
|
defaultHireMode: 'job',
|
|
127
127
|
lockCopy: 'Hire MANdy to unlock autonomous multi-role orchestration — MANdy plans the job sequence, runs sub-agents in parallel, coaches them through verification loops, and hands back a synthesized DRAFT for your approval.'
|
|
@@ -175,7 +175,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
175
175
|
personaKey: 'casey',
|
|
176
176
|
bundleId: 'persona-casey-core',
|
|
177
177
|
catalogMetadata: buildCatalogMetadata('casey', ['support-case-resolution', 'support-sop-operationalization', 'support-system-operationalization', 'support-playbook-evaluation']),
|
|
178
|
-
protectedJobs: ['crm-account-health-review', 'crm-case-resolution', 'customer-health-review', 'loyalty-program-management', 'survey-campaign-management', 'support-queue-management', 'support-case-resolution', 'support-sop-operationalization', 'support-system-operationalization', 'support-playbook-evaluation'],
|
|
178
|
+
protectedJobs: ['crm-account-health-review', 'crm-case-resolution', 'customer-health-review', 'loyalty-program-management', 'survey-campaign-management', 'support-queue-management', 'support-case-resolution', 'support-sop-operationalization', 'support-system-operationalization', 'support-playbook-evaluation', 'user-survey-management'],
|
|
179
179
|
protectedAliases: ['customer-success', 'customer-support', 'csm', 'support'],
|
|
180
180
|
defaultHireMode: 'job',
|
|
181
181
|
lockCopy: 'Hire CaSey to unlock customer success and support work for this request.'
|
|
@@ -205,7 +205,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
205
205
|
personaKey: 'mona',
|
|
206
206
|
bundleId: 'persona-mona-core',
|
|
207
207
|
catalogMetadata: buildCatalogMetadata('mona', ['financial-analysis', 'fpa-and-forecasting', 'monthly-close-review']),
|
|
208
|
-
protectedJobs: ['financial-analysis', 'fpa-and-forecasting', 'monthly-close-review', 'tax-strategy-planning'],
|
|
208
|
+
protectedJobs: ['financial-analysis', 'fpa-and-forecasting', 'monthly-close-review', 'tax-strategy-planning', 'aws-activate-credits-application', 'google-cloud-credits-application', 'microsoft-azure-credits-application', 'invoice-generation', 'business-banking-setup'],
|
|
209
209
|
protectedAliases: ['finance', 'financial-modeling', 'fpa', 'bookkeeping'],
|
|
210
210
|
defaultHireMode: 'job',
|
|
211
211
|
lockCopy: 'Hire MONa to unlock financial modeling, FP&A, and tax strategy work for this request.'
|
|
@@ -214,7 +214,7 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
214
214
|
personaKey: 'sreya',
|
|
215
215
|
bundleId: 'persona-sreya-core',
|
|
216
216
|
catalogMetadata: buildCatalogMetadata('sreya', ['slo-design-and-implementation', 'incident-response', 'reliability-review']),
|
|
217
|
-
protectedJobs: ['slo-design-and-implementation', 'incident-response', 'reliability-review'],
|
|
217
|
+
protectedJobs: ['slo-design-and-implementation', 'incident-response', 'reliability-review', 'production-readiness-review'],
|
|
218
218
|
protectedAliases: ['sre', 'reliability', 'incident-response', 'on-call'],
|
|
219
219
|
defaultHireMode: 'job',
|
|
220
220
|
lockCopy: 'Hire SREya to unlock SLO governance, incident response, and production reliability work for this request.'
|
|
@@ -231,7 +231,8 @@ exports.PERSONA_CAPABILITY_BUNDLES = {
|
|
|
231
231
|
'procurement-negotiation-prep',
|
|
232
232
|
'purchase-approval-and-po-package',
|
|
233
233
|
'equipment-acceptance-and-supplier-retrospective',
|
|
234
|
-
'supplier-performance-review'
|
|
234
|
+
'supplier-performance-review',
|
|
235
|
+
'rfp-response-preparation'
|
|
235
236
|
],
|
|
236
237
|
protectedAliases: ['procurement', 'sourcing', 'purchasing', 'supplier-management'],
|
|
237
238
|
defaultHireMode: 'job',
|
|
@@ -266,6 +267,9 @@ function getPersonaCapabilityBundle(personaKey) {
|
|
|
266
267
|
return exports.PERSONA_CAPABILITY_BUNDLES[personaKey];
|
|
267
268
|
}
|
|
268
269
|
function getProtectedPersonaForJob(jobName) {
|
|
270
|
+
if (isFreeJob(jobName)) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
269
273
|
return PROTECTED_JOB_TO_PERSONA.get(jobName) || null;
|
|
270
274
|
}
|
|
271
275
|
function listPersonaCapabilityBundles() {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PaymentRepository = void 0;
|
|
4
|
+
const COLLECTION_NAME = 'fraim_payments';
|
|
5
|
+
class PaymentRepository {
|
|
6
|
+
constructor(client, dbName = 'fraim') {
|
|
7
|
+
this.db = client.db(dbName);
|
|
8
|
+
this.collection = this.db.collection(COLLECTION_NAME);
|
|
9
|
+
}
|
|
10
|
+
async ensureIndexes() {
|
|
11
|
+
await this.collection.createIndex({ email: 1 });
|
|
12
|
+
await this.collection.createIndex({ timestamp: -1 });
|
|
13
|
+
await this.collection.createIndex({ status: 1 });
|
|
14
|
+
await this.collection.createIndex({ stripeCustomerId: 1 });
|
|
15
|
+
}
|
|
16
|
+
async createPayment(payment) {
|
|
17
|
+
const result = await this.collection.insertOne(payment);
|
|
18
|
+
return { ...payment, _id: result.insertedId.toString() };
|
|
19
|
+
}
|
|
20
|
+
async updatePaymentStatus(stripePaymentIntentId, status, metadata) {
|
|
21
|
+
const result = await this.collection.updateOne({ stripePaymentIntentId }, {
|
|
22
|
+
$set: {
|
|
23
|
+
status,
|
|
24
|
+
...(metadata && { metadata })
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return result.modifiedCount > 0;
|
|
28
|
+
}
|
|
29
|
+
async getPaymentById(id) {
|
|
30
|
+
return await this.collection.findOne({ _id: id });
|
|
31
|
+
}
|
|
32
|
+
async getPaymentByStripePaymentIntent(stripePaymentIntentId) {
|
|
33
|
+
return await this.collection.findOne({ stripePaymentIntentId });
|
|
34
|
+
}
|
|
35
|
+
async getPaymentsByEmail(email) {
|
|
36
|
+
return await this.collection.find({ email }).sort({ timestamp: -1 }).toArray();
|
|
37
|
+
}
|
|
38
|
+
async listPayments(filters) {
|
|
39
|
+
const query = {};
|
|
40
|
+
if (filters.plan)
|
|
41
|
+
query.plan = filters.plan;
|
|
42
|
+
if (filters.status)
|
|
43
|
+
query.status = filters.status;
|
|
44
|
+
if (filters.startDate || filters.endDate) {
|
|
45
|
+
query.timestamp = {};
|
|
46
|
+
if (filters.startDate)
|
|
47
|
+
query.timestamp.$gte = filters.startDate;
|
|
48
|
+
if (filters.endDate)
|
|
49
|
+
query.timestamp.$lte = filters.endDate;
|
|
50
|
+
}
|
|
51
|
+
const total = await this.collection.countDocuments(query);
|
|
52
|
+
const payments = await this.collection
|
|
53
|
+
.find(query)
|
|
54
|
+
.sort({ timestamp: -1 })
|
|
55
|
+
.skip(filters.offset || 0)
|
|
56
|
+
.limit(filters.limit || 50)
|
|
57
|
+
.toArray();
|
|
58
|
+
return { payments, total };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.PaymentRepository = PaymentRepository;
|
|
@@ -607,12 +607,12 @@ class FirstRunSessionService {
|
|
|
607
607
|
persistShellPath();
|
|
608
608
|
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
609
609
|
if (detectedIDEs.length > 0) {
|
|
610
|
-
await (0, auto_mcp_setup_1.autoConfigureMCP)(this.key,
|
|
610
|
+
await (0, auto_mcp_setup_1.autoConfigureMCP)(this.key, detectedIDEs.map((ide) => ide.name));
|
|
611
611
|
}
|
|
612
612
|
// Write config.json after autoConfigureMCP so detectRowsOnLoad can use its
|
|
613
613
|
// existence as a signal that IDE setup completed. Writing it before would cause
|
|
614
614
|
// the wizard to mark this row 'ok' on retry before IDEs are actually configured.
|
|
615
|
-
(0, setup_1.saveGlobalConfig)(this.key, 'conversational'
|
|
615
|
+
(0, setup_1.saveGlobalConfig)(this.key, 'conversational');
|
|
616
616
|
const { syncUserLevelArtifacts } = await Promise.resolve().then(() => __importStar(require('../cli/setup/user-level-sync')));
|
|
617
617
|
await syncUserLevelArtifacts();
|
|
618
618
|
const { installSlashCommands, installGlobalRules } = await Promise.resolve().then(() => __importStar(require('../cli/setup/ide-global-integration')));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRepositoryInfo = exports.getConfigValue = exports.loadFraimConfig = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Backward-compatible re-export.
|
|
6
|
+
* Canonical config loader lives in src/core/config-loader.ts.
|
|
7
|
+
*/
|
|
8
|
+
var config_loader_1 = require("../core/config-loader");
|
|
9
|
+
Object.defineProperty(exports, "loadFraimConfig", { enumerable: true, get: function () { return config_loader_1.loadFraimConfig; } });
|
|
10
|
+
Object.defineProperty(exports, "getConfigValue", { enumerable: true, get: function () { return config_loader_1.getConfigValue; } });
|
|
11
|
+
Object.defineProperty(exports, "getRepositoryInfo", { enumerable: true, get: function () { return config_loader_1.getRepositoryInfo; } });
|