fraim-framework 2.0.35 → 2.0.37

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.
Files changed (159) hide show
  1. package/dist/registry/scripts/cleanup-branch.js +62 -33
  2. package/dist/registry/scripts/generate-engagement-emails.js +119 -44
  3. package/dist/registry/scripts/newsletter-helpers.js +208 -268
  4. package/dist/registry/scripts/profile-server.js +387 -0
  5. package/dist/scripts/build-stub-registry.js +108 -0
  6. package/dist/src/cli/commands/doctor.js +5 -5
  7. package/dist/src/cli/commands/sync.js +33 -19
  8. package/dist/tests/test-client-scripts-validation.js +133 -0
  9. package/dist/tests/test-package-size.js +88 -0
  10. package/dist/tests/test-script-location-independence.js +76 -28
  11. package/dist/tests/test-stub-registry.js +120 -0
  12. package/dist/tests/test-sync-stubs.js +143 -0
  13. package/package.json +7 -9
  14. package/registry/scripts/cleanup-branch.ts +341 -0
  15. package/registry/scripts/generate-engagement-emails.ts +830 -0
  16. package/registry/scripts/markdown-to-pdf.js +7 -3
  17. package/registry/scripts/newsletter-helpers.ts +777 -0
  18. package/registry/scripts/profile-server.ts +424 -0
  19. package/registry/scripts/run-thank-you-workflow.ts +122 -0
  20. package/registry/scripts/send-newsletter-simple.ts +102 -0
  21. package/registry/scripts/send-thank-you-emails.ts +57 -0
  22. package/registry/stubs/workflows/bootstrap/create-architecture.md +11 -0
  23. package/registry/stubs/workflows/bootstrap/detect-broken-windows.md +11 -0
  24. package/registry/stubs/workflows/bootstrap/evaluate-code-quality.md +11 -0
  25. package/registry/stubs/workflows/bootstrap/verify-test-coverage.md +11 -0
  26. package/registry/stubs/workflows/business-development/create-business-plan.md +11 -0
  27. package/registry/stubs/workflows/business-development/ideate-business-opportunity.md +11 -0
  28. package/registry/stubs/workflows/business-development/price-product.md +18 -0
  29. package/registry/stubs/workflows/convert-to-pdf.md +11 -0
  30. package/registry/stubs/workflows/customer-development/insight-analysis.md +11 -0
  31. package/registry/stubs/workflows/customer-development/insight-triage.md +11 -0
  32. package/registry/stubs/workflows/customer-development/interview-preparation.md +11 -0
  33. package/registry/stubs/workflows/customer-development/linkedin-outreach.md +11 -0
  34. package/registry/stubs/workflows/customer-development/strategic-brainstorming.md +11 -0
  35. package/registry/stubs/workflows/customer-development/thank-customers.md +11 -0
  36. package/registry/stubs/workflows/customer-development/weekly-newsletter.md +11 -0
  37. package/registry/stubs/workflows/deploy/cloud-deployment.md +11 -0
  38. package/registry/stubs/workflows/improve-fraim/contribute.md +11 -0
  39. package/registry/stubs/workflows/improve-fraim/file-issue.md +11 -0
  40. package/registry/stubs/workflows/marketing/content-creation.md +11 -0
  41. package/registry/stubs/workflows/marketing/hbr-article.md +11 -0
  42. package/registry/stubs/workflows/marketing/launch-checklist.md +11 -0
  43. package/registry/stubs/workflows/marketing/marketing-strategy.md +11 -0
  44. package/registry/stubs/workflows/marketing/storytelling.md +11 -0
  45. package/registry/stubs/workflows/performance/analyze-performance.md +11 -0
  46. package/registry/stubs/workflows/product-building/design.md +11 -0
  47. package/registry/stubs/workflows/product-building/implement.md +12 -0
  48. package/registry/stubs/workflows/product-building/iterate-on-pr-comments.md +11 -0
  49. package/registry/stubs/workflows/product-building/prep-issue.md +11 -0
  50. package/registry/stubs/workflows/product-building/prototype.md +11 -0
  51. package/registry/stubs/workflows/product-building/resolve.md +11 -0
  52. package/registry/stubs/workflows/product-building/retrospect.md +11 -0
  53. package/registry/stubs/workflows/product-building/spec.md +11 -0
  54. package/registry/stubs/workflows/product-building/test.md +11 -0
  55. package/registry/stubs/workflows/quality-assurance/browser-validation.md +11 -0
  56. package/registry/stubs/workflows/quality-assurance/iterative-improvement-cycle.md +11 -0
  57. package/registry/stubs/workflows/replicate/replicate-discovery.md +11 -0
  58. package/registry/stubs/workflows/replicate/replicate-to-issues.md +11 -0
  59. package/registry/stubs/workflows/reviewer/review-implementation-vs-design-spec.md +11 -0
  60. package/registry/stubs/workflows/reviewer/review-implementation-vs-feature-spec.md +11 -0
  61. package/registry/stubs/workflows/startup-credits/aws-activate-application.md +11 -0
  62. package/registry/stubs/workflows/startup-credits/google-cloud-application.md +11 -0
  63. package/registry/stubs/workflows/startup-credits/microsoft-azure-application.md +11 -0
  64. package/.github/workflows/ci.yml +0 -65
  65. package/.github/workflows/deploy-fraim.yml +0 -87
  66. package/.github/workflows/phase-change.yml +0 -251
  67. package/.github/workflows/status-change.yml +0 -68
  68. package/.github/workflows/sync-on-pr-review.yml +0 -66
  69. package/examples/simple-webapp/TESTING.md +0 -62
  70. package/examples/simple-webapp/example-test.ts +0 -186
  71. package/registry/github/workflows/ci.yml +0 -51
  72. package/registry/github/workflows/phase-change.yml +0 -251
  73. package/registry/github/workflows/status-change.yml +0 -68
  74. package/registry/github/workflows/sync-on-pr-review.yml +0 -66
  75. package/registry/mcp-template.jsonc +0 -29
  76. package/registry/rules/agent-success-criteria.md +0 -52
  77. package/registry/rules/agent-testing-guidelines.md +0 -502
  78. package/registry/rules/architecture.md +0 -52
  79. package/registry/rules/communication.md +0 -122
  80. package/registry/rules/continuous-learning.md +0 -55
  81. package/registry/rules/debugging-multitenancy-issues.md +0 -85
  82. package/registry/rules/ephemeral-execution.md +0 -57
  83. package/registry/rules/git-safe-commands.md +0 -34
  84. package/registry/rules/hitl-ppe-record-analysis.md +0 -302
  85. package/registry/rules/integrity-and-test-ethics.md +0 -275
  86. package/registry/rules/local-development.md +0 -254
  87. package/registry/rules/merge-requirements.md +0 -231
  88. package/registry/rules/simplicity.md +0 -118
  89. package/registry/rules/software-development-lifecycle.md +0 -105
  90. package/registry/rules/spike-first-development.md +0 -205
  91. package/registry/rules/successful-debugging-patterns.md +0 -491
  92. package/registry/rules/telemetry.md +0 -67
  93. package/registry/templates/bootstrap/ARCHITECTURE-TEMPLATE.md +0 -53
  94. package/registry/templates/bootstrap/CODE-QUALITY-REPORT-TEMPLATE.md +0 -37
  95. package/registry/templates/bootstrap/TEST-COVERAGE-REPORT-TEMPLATE.md +0 -35
  96. package/registry/templates/business-development/IDEATION-REPORT-TEMPLATE.md +0 -29
  97. package/registry/templates/business-development/PRICING-STRATEGY-TEMPLATE.md +0 -126
  98. package/registry/templates/customer-development/customer-interview-template.md +0 -99
  99. package/registry/templates/customer-development/follow-up-email-templates.md +0 -132
  100. package/registry/templates/customer-development/insight-analysis-template.md +0 -74
  101. package/registry/templates/customer-development/strategic-recommendations-template.md +0 -53
  102. package/registry/templates/customer-development/thank-you-email-template.html +0 -124
  103. package/registry/templates/customer-development/thank-you-note-template.md +0 -16
  104. package/registry/templates/customer-development/triage-log-template.md +0 -278
  105. package/registry/templates/customer-development/weekly-newsletter-template.html +0 -204
  106. package/registry/templates/evidence/Design-Evidence.md +0 -30
  107. package/registry/templates/evidence/Implementation-BugEvidence.md +0 -86
  108. package/registry/templates/evidence/Implementation-FeatureEvidence.md +0 -121
  109. package/registry/templates/evidence/Spec-Evidence.md +0 -19
  110. package/registry/templates/help/HelpNeeded.md +0 -14
  111. package/registry/templates/marketing/HBR-ARTICLE-TEMPLATE.md +0 -66
  112. package/registry/templates/marketing/STORYTELLING-TEMPLATE.md +0 -130
  113. package/registry/templates/replicate/implementation-checklist.md +0 -39
  114. package/registry/templates/replicate/use-cases-template.md +0 -88
  115. package/registry/templates/retrospective/RETROSPECTIVE-TEMPLATE.md +0 -55
  116. package/registry/templates/specs/BUGSPEC-TEMPLATE.md +0 -37
  117. package/registry/templates/specs/FEATURESPEC-TEMPLATE.md +0 -29
  118. package/registry/templates/specs/TECHSPEC-TEMPLATE.md +0 -39
  119. package/registry/workflows/bootstrap/create-architecture.md +0 -38
  120. package/registry/workflows/bootstrap/evaluate-code-quality.md +0 -36
  121. package/registry/workflows/bootstrap/verify-test-coverage.md +0 -37
  122. package/registry/workflows/business-development/create-business-plan.md +0 -737
  123. package/registry/workflows/business-development/ideate-business-opportunity.md +0 -55
  124. package/registry/workflows/business-development/price-product.md +0 -325
  125. package/registry/workflows/convert-to-pdf.md +0 -235
  126. package/registry/workflows/customer-development/insight-analysis.md +0 -156
  127. package/registry/workflows/customer-development/insight-triage.md +0 -933
  128. package/registry/workflows/customer-development/interview-preparation.md +0 -421
  129. package/registry/workflows/customer-development/linkedin-outreach.md +0 -593
  130. package/registry/workflows/customer-development/strategic-brainstorming.md +0 -146
  131. package/registry/workflows/customer-development/thank-customers.md +0 -203
  132. package/registry/workflows/customer-development/weekly-newsletter.md +0 -366
  133. package/registry/workflows/deploy/cloud-deployment.md +0 -310
  134. package/registry/workflows/improve-fraim/contribute.md +0 -32
  135. package/registry/workflows/improve-fraim/file-issue.md +0 -32
  136. package/registry/workflows/marketing/content-creation.md +0 -37
  137. package/registry/workflows/marketing/hbr-article.md +0 -73
  138. package/registry/workflows/marketing/launch-checklist.md +0 -37
  139. package/registry/workflows/marketing/marketing-strategy.md +0 -45
  140. package/registry/workflows/marketing/storytelling.md +0 -65
  141. package/registry/workflows/performance/analyze-performance.md +0 -65
  142. package/registry/workflows/product-building/design.md +0 -130
  143. package/registry/workflows/product-building/implement.md +0 -315
  144. package/registry/workflows/product-building/iterate-on-pr-comments.md +0 -70
  145. package/registry/workflows/product-building/prep-issue.md +0 -43
  146. package/registry/workflows/product-building/prototype.md +0 -60
  147. package/registry/workflows/product-building/resolve.md +0 -164
  148. package/registry/workflows/product-building/retrospect.md +0 -86
  149. package/registry/workflows/product-building/spec.md +0 -117
  150. package/registry/workflows/product-building/test.md +0 -120
  151. package/registry/workflows/quality-assurance/browser-validation.md +0 -221
  152. package/registry/workflows/quality-assurance/iterative-improvement-cycle.md +0 -562
  153. package/registry/workflows/replicate/replicate-discovery.md +0 -336
  154. package/registry/workflows/replicate/replicate-to-issues.md +0 -319
  155. package/registry/workflows/reviewer/review-implementation-vs-design-spec.md +0 -632
  156. package/registry/workflows/reviewer/review-implementation-vs-feature-spec.md +0 -669
  157. package/registry/workflows/startup-credits/aws-activate-application.md +0 -535
  158. package/registry/workflows/startup-credits/google-cloud-application.md +0 -647
  159. package/registry/workflows/startup-credits/microsoft-azure-application.md +0 -538
@@ -5,9 +5,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const child_process_1 = require("child_process");
8
+ const fs_1 = require("fs");
9
+ const path_1 = require("path");
8
10
  const dotenv_1 = __importDefault(require("dotenv"));
9
11
  // Load environment variables
10
12
  dotenv_1.default.config({ override: true });
13
+ // Self-contained utility functions (no FRAIM internal imports)
14
+ function extractIssueNumber(branchName) {
15
+ const match = branchName.match(/(\d+)/);
16
+ return match ? match[1] : '';
17
+ }
18
+ function getCurrentGitBranch() {
19
+ try {
20
+ return (0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf8' }).trim();
21
+ }
22
+ catch (error) {
23
+ return 'unknown';
24
+ }
25
+ }
26
+ function loadClientConfig() {
27
+ const configPath = (0, path_1.join)(process.cwd(), '.fraim', 'config.json');
28
+ if (!(0, fs_1.existsSync)(configPath)) {
29
+ throw new Error('.fraim/config.json not found. Run fraim init first.');
30
+ }
31
+ return JSON.parse((0, fs_1.readFileSync)(configPath, 'utf-8'));
32
+ }
33
+ function getEnvOr(keys, fallback) {
34
+ for (const key of keys) {
35
+ const value = process.env[key];
36
+ if (value && value.length)
37
+ return value;
38
+ }
39
+ return fallback;
40
+ }
11
41
  class BranchCleanup {
12
42
  constructor(options = {}) {
13
43
  this.options = {
@@ -18,7 +48,6 @@ class BranchCleanup {
18
48
  };
19
49
  }
20
50
  async insertYourCodeHere(branchName) {
21
- const { extractIssueNumber } = require('../../src/utils/git-utils');
22
51
  const branchPattern = "branch_" + extractIssueNumber(branchName) + "%";
23
52
  this.log(`Attempting to fetch and run DB cleanup for pattern: ${branchPattern}`);
24
53
  // Historically this called: npx tsx scripts/database/cleanup-mongo-schemas.ts
@@ -217,38 +246,38 @@ for (let i = 0; i < args.length; i++) {
217
246
  break;
218
247
  case '--help':
219
248
  case '-h':
220
- console.log(`
221
- 🧹 Branch Cleanup Script
222
-
223
- Usage:
224
- npx tsx scripts/cleanup-branch.ts [options]
225
-
226
- Options:
227
- --branch, -b <name> Specific branch name to cleanup (default: current branch)
228
- --force, -f Continue even if some operations fail
229
- --skip-project-cleanup Skip project-specific cleanup
230
- --skip-git Skip Git branch deletion
231
- --help, -h Show this help message
232
-
233
- Examples:
234
- # Cleanup current branch with default settings
235
- npx tsx <cleanup-script-path>
236
-
237
- # Cleanup specific branch
238
- npx tsx <cleanup-script-path> --branch feature/123
239
-
240
- # Force cleanup even if some operations fail
241
- npx tsx <cleanup-script-path> --force
242
-
243
- # Skip project-specific cleanup (only do Git cleanup)
244
- npx tsx <cleanup-script-path> --skip-project-cleanup
245
-
246
- This script performs the following cleanup operations:
247
- 1. 🗄️ Project-specific cleanup (calls configured cleanup script)
248
- 2. 🌿 Git branch deletion (remote and local)
249
- 3. ✅ Verification of cleanup completion
250
-
251
- ⚠️ WARNING: This script will permanently delete branches and data!
249
+ console.log(`
250
+ 🧹 Branch Cleanup Script
251
+
252
+ Usage:
253
+ npx tsx scripts/cleanup-branch.ts [options]
254
+
255
+ Options:
256
+ --branch, -b <name> Specific branch name to cleanup (default: current branch)
257
+ --force, -f Continue even if some operations fail
258
+ --skip-project-cleanup Skip project-specific cleanup
259
+ --skip-git Skip Git branch deletion
260
+ --help, -h Show this help message
261
+
262
+ Examples:
263
+ # Cleanup current branch with default settings
264
+ npx tsx <cleanup-script-path>
265
+
266
+ # Cleanup specific branch
267
+ npx tsx <cleanup-script-path> --branch feature/123
268
+
269
+ # Force cleanup even if some operations fail
270
+ npx tsx <cleanup-script-path> --force
271
+
272
+ # Skip project-specific cleanup (only do Git cleanup)
273
+ npx tsx <cleanup-script-path> --skip-project-cleanup
274
+
275
+ This script performs the following cleanup operations:
276
+ 1. 🗄️ Project-specific cleanup (calls configured cleanup script)
277
+ 2. 🌿 Git branch deletion (remote and local)
278
+ 3. ✅ Verification of cleanup completion
279
+
280
+ ⚠️ WARNING: This script will permanently delete branches and data!
252
281
  `);
253
282
  process.exit(0);
254
283
  }
@@ -49,8 +49,83 @@ const child_process_1 = require("child_process");
49
49
  const fs_1 = require("fs");
50
50
  const mongodb_1 = require("mongodb");
51
51
  const path_1 = require("path");
52
- const git_utils_js_1 = require("../../src/utils/git-utils.js");
53
- const fraim_config_1 = require("./fraim-config");
52
+ // Self-contained utility functions (no FRAIM internal imports)
53
+ function determineDatabaseName() {
54
+ const env = process.env.NODE_ENV || process.env.ENVIRONMENT;
55
+ // If explicitly set to ppe/staging, use that; otherwise default to prod
56
+ if (env === 'ppe' || env === 'staging') {
57
+ return 'fraim_ppe';
58
+ }
59
+ // Default to production
60
+ return process.env.MONGO_DB_NAME || 'fraim_prod';
61
+ }
62
+ function determineSchema(branchName) {
63
+ if (branchName.includes('ppe') || branchName.includes('staging'))
64
+ return 'ppe';
65
+ return 'prod';
66
+ }
67
+ function getCurrentGitBranch() {
68
+ try {
69
+ return (0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf8' }).trim();
70
+ }
71
+ catch (error) {
72
+ return 'master';
73
+ }
74
+ }
75
+ function loadClientConfig() {
76
+ const configPath = (0, path_1.join)(process.cwd(), '.fraim', 'config.json');
77
+ if (!(0, fs_1.existsSync)(configPath)) {
78
+ throw new Error('.fraim/config.json not found. Run fraim init first.');
79
+ }
80
+ return JSON.parse((0, fs_1.readFileSync)(configPath, 'utf-8'));
81
+ }
82
+ function getEnvOr(keys, fallback) {
83
+ for (const key of keys) {
84
+ const value = process.env[key];
85
+ if (value && value.length)
86
+ return value;
87
+ }
88
+ return fallback;
89
+ }
90
+ // Load configuration
91
+ const config = loadClientConfig();
92
+ const personaName = config.persona.name;
93
+ const personaDisplayNameDefault = config.persona.displayNamePattern.replace('{executiveName}', 'Your');
94
+ const fraimConfig = {
95
+ repoOwner: config.git.repoOwner || 'mathursrus',
96
+ repoName: config.git.repoName || 'fraim-repo',
97
+ projectName: 'FRAIM',
98
+ personaName,
99
+ personaPronouns: getEnvOr(['FRAIM_PERSONA_PRONOUNS'], 'they/them'),
100
+ personaDisplayName: getEnvOr(['FRAIM_PERSONA_DISPLAY_NAME'], personaDisplayNameDefault),
101
+ personaDisplayNamePattern: config.persona.displayNamePattern,
102
+ personaThankYouSignature: config.persona.emailSignature,
103
+ defaultEmail: getEnvOr(['FRAIM_DEFAULT_EMAIL'], 'agent@example.com'),
104
+ prodDefaultEmail: getEnvOr(['PROD_FRAIM_DEFAULT_EMAIL'], 'agent@example.com'),
105
+ defaultAccessToken: getEnvOr(['FRAIM_DEFAULT_ACCESS_TOKEN'], ''),
106
+ defaultRefreshToken: getEnvOr(['FRAIM_DEFAULT_REFRESH_TOKEN'], ''),
107
+ prodAccessToken: getEnvOr(['PROD_FRAIM_DEFAULT_ACCESS_TOKEN'], ''),
108
+ prodRefreshToken: getEnvOr(['PROD_FRAIM_DEFAULT_REFRESH_TOKEN'], ''),
109
+ defaultOAuthClientId: getEnvOr(['FRAIM_DEFAULT_OAUTH_CLIENT_ID'], ''),
110
+ defaultOAuthClientSecret: getEnvOr(['FRAIM_DEFAULT_OAUTH_CLIENT_SECRET'], ''),
111
+ prodOAuthClientId: getEnvOr(['PROD_FRAIM_DEFAULT_OAUTH_CLIENT_ID'], ''),
112
+ prodOAuthClientSecret: getEnvOr(['PROD_FRAIM_DEFAULT_OAUTH_CLIENT_SECRET'], ''),
113
+ identityCollection: config.database?.identityCollection || 'Identity',
114
+ executiveCollection: config.database?.executiveCollection || 'Executive',
115
+ newsletterTitle: 'Weekly Update',
116
+ newsletterCtaText: 'Learn More',
117
+ newsletterUrl: getEnvOr(['FRAIM_NEWSLETTER_URL'], ''),
118
+ issueRepoUrl: `https://github.com/${config.git.repoOwner}/${config.git.repoName}.git`,
119
+ identityTokensCollection: 'Tokens',
120
+ webAppUrl: config.marketing?.websiteUrl || getEnvOr(['FRAIM_WEB_APP_URL'], 'http://localhost:3000'),
121
+ chatUrl: config.marketing?.chatUrl || getEnvOr(['FRAIM_CHAT_URL'], ''),
122
+ };
123
+ function formatExecutiveDisplayName(executiveName) {
124
+ return config.persona.displayNamePattern.replace('{executiveName}', executiveName);
125
+ }
126
+ function formatPersonaSignature() {
127
+ return `With gratitude,\n${fraimConfig.personaThankYouSignature}\n${personaName} - Your AI Executive Assistant\n\n`;
128
+ }
54
129
  // Get template path (relative to script location)
55
130
  function getTemplatePath() {
56
131
  // Script is at <this-path>
@@ -123,7 +198,7 @@ async function getResolvedIssues(date) {
123
198
  }
124
199
  // Use ">YYYY-MM-DD" format to get issues updated AFTER the date (not on the date)
125
200
  // GitHub CLI requires quotes around the comparison operator
126
- const command = `gh search issues --repo=${fraim_config_1.fraimConfig.repoOwner}/${fraim_config_1.fraimConfig.repoName} --state=closed --updated=">${date}" --label=user-reported --json number,title,body,labels,closedAt,author`;
201
+ const command = `gh search issues --repo=${fraimConfig.repoOwner}/${fraimConfig.repoName} --state=closed --updated=">${date}" --label=user-reported --json number,title,body,labels,closedAt,author`;
127
202
  const output = (0, child_process_1.execSync)(command, { encoding: 'utf-8' });
128
203
  return JSON.parse(output);
129
204
  }
@@ -141,7 +216,7 @@ function getDatabaseName() {
141
216
  const env = process.env.NODE_ENV || process.env.ENVIRONMENT;
142
217
  // If explicitly set to ppe/staging, use that; otherwise default to prod
143
218
  if (env === 'ppe' || env === 'staging') {
144
- return (0, git_utils_js_1.determineDatabaseName)();
219
+ return determineDatabaseName();
145
220
  }
146
221
  // Default to production
147
222
  return process.env.MONGO_DB_NAME || 'fraim_prod';
@@ -153,7 +228,7 @@ function getCollectionName(baseName) {
153
228
  const env = process.env.NODE_ENV || process.env.ENVIRONMENT;
154
229
  // If explicitly set to ppe/staging, use that schema; otherwise default to prod
155
230
  if (env === 'ppe' || env === 'staging') {
156
- const schema = (0, git_utils_js_1.determineSchema)((0, git_utils_js_1.getCurrentGitBranch)());
231
+ const schema = determineSchema(getCurrentGitBranch());
157
232
  return `${schema}_${baseName}`;
158
233
  }
159
234
  // Default to prod schema
@@ -184,15 +259,15 @@ async function getPersonaEmailForExecutive(executiveId) {
184
259
  const { MongoClient } = await Promise.resolve().then(() => __importStar(require('mongodb')));
185
260
  const mongoUrl = process.env.PROD_MONGO_DATABASE_URL || process.env.MONGO_DATABASE_URL;
186
261
  if (!mongoUrl) {
187
- console.warn(`⚠️ PROD_MONGO_DATABASE_URL not set, using default ${fraim_config_1.fraimConfig.personaName} email`);
188
- return fraim_config_1.fraimConfig.defaultEmail;
262
+ console.warn(`⚠️ PROD_MONGO_DATABASE_URL not set, using default ${fraimConfig.personaName} email`);
263
+ return fraimConfig.defaultEmail;
189
264
  }
190
265
  const client = new MongoClient(mongoUrl);
191
266
  try {
192
267
  await client.connect();
193
268
  const dbName = getDatabaseName();
194
269
  const db = client.db(dbName);
195
- const collectionName = getCollectionName(fraim_config_1.fraimConfig.identityCollection);
270
+ const collectionName = getCollectionName(fraimConfig.identityCollection);
196
271
  // Query the identity collection (defaults to prod)
197
272
  let identity = await db.collection(collectionName).findOne({
198
273
  executive_id: executiveId,
@@ -206,11 +281,11 @@ async function getPersonaEmailForExecutive(executiveId) {
206
281
  if (identity && identity.email) {
207
282
  return identity.email;
208
283
  }
209
- return fraim_config_1.fraimConfig.defaultEmail;
284
+ return fraimConfig.defaultEmail;
210
285
  }
211
286
  catch (error) {
212
- console.warn(`⚠️ Could not get ${fraim_config_1.fraimConfig.personaName} email for executive ${executiveId}:`, error);
213
- return fraim_config_1.fraimConfig.defaultEmail;
287
+ console.warn(`⚠️ Could not get ${fraimConfig.personaName} email for executive ${executiveId}:`, error);
288
+ return fraimConfig.defaultEmail;
214
289
  }
215
290
  finally {
216
291
  await client.close();
@@ -268,7 +343,7 @@ async function sendCustomerMail(candidatesFilePath, executiveId) {
268
343
  await client.connect();
269
344
  const dbName = getDatabaseName();
270
345
  const db = client.db(dbName);
271
- const collectionName = getCollectionName(fraim_config_1.fraimConfig.identityCollection);
346
+ const collectionName = getCollectionName(fraimConfig.identityCollection);
272
347
  const identity = await db.collection(collectionName).findOne({
273
348
  executive_id: candidate.executive.id,
274
349
  status: 'active'
@@ -280,10 +355,10 @@ async function sendCustomerMail(candidatesFilePath, executiveId) {
280
355
  access_token: identity.access_token,
281
356
  refresh_token: identity.refresh_token
282
357
  };
283
- console.log(`Found ${fraim_config_1.fraimConfig.personaName} tokens in ${dbName} database for ${candidate.from.email}`);
358
+ console.log(`Found ${fraimConfig.personaName} tokens in ${dbName} database for ${candidate.from.email}`);
284
359
  }
285
360
  else {
286
- console.warn(`No ${fraim_config_1.fraimConfig.personaName} tokens found in ${dbName} database for executive ${candidate.executive.id}`);
361
+ console.warn(`No ${fraimConfig.personaName} tokens found in ${dbName} database for executive ${candidate.executive.id}`);
287
362
  }
288
363
  }
289
364
  finally {
@@ -291,7 +366,7 @@ async function sendCustomerMail(candidatesFilePath, executiveId) {
291
366
  }
292
367
  }
293
368
  catch (error) {
294
- console.warn(`Could not get ${fraim_config_1.fraimConfig.personaName} tokens from database for executive ${candidate.executive.id}:`, error);
369
+ console.warn(`Could not get ${fraimConfig.personaName} tokens from database for executive ${candidate.executive.id}:`, error);
295
370
  }
296
371
  }
297
372
  // Generate plain text body for fallback (from structured format if available)
@@ -335,7 +410,7 @@ async function sendSingleEmail(params, executive, personaTokens) {
335
410
  let refreshToken;
336
411
  if (personaTokens?.access_token && personaTokens?.refresh_token) {
337
412
  // Use persona identity tokens (preferred - ensures correct From address)
338
- console.log(`🔑 Using ${fraim_config_1.fraimConfig.personaName} identity tokens for ${fromEmail}`);
413
+ console.log(`🔑 Using ${fraimConfig.personaName} identity tokens for ${fromEmail}`);
339
414
  accessToken = personaTokens.access_token;
340
415
  refreshToken = personaTokens.refresh_token;
341
416
  }
@@ -347,11 +422,11 @@ async function sendSingleEmail(params, executive, personaTokens) {
347
422
  }
348
423
  else {
349
424
  // Use default persona tokens as last resort
350
- console.log(`🔑 Using default ${fraim_config_1.fraimConfig.personaName} tokens as fallback`);
351
- accessToken = fraim_config_1.fraimConfig.defaultAccessToken;
352
- refreshToken = fraim_config_1.fraimConfig.defaultRefreshToken;
425
+ console.log(`🔑 Using default ${fraimConfig.personaName} tokens as fallback`);
426
+ accessToken = fraimConfig.defaultAccessToken;
427
+ refreshToken = fraimConfig.defaultRefreshToken;
353
428
  if (!accessToken || !refreshToken) {
354
- throw new Error(`${fraim_config_1.fraimConfig.personaName} Gmail tokens not found. Need either identity tokens, executive tokens, or default tokens in environment variables.`);
429
+ throw new Error(`${fraimConfig.personaName} Gmail tokens not found. Need either identity tokens, executive tokens, or default tokens in environment variables.`);
355
430
  }
356
431
  }
357
432
  // Verify the From email matches the authenticated account (Gmail requirement)
@@ -416,8 +491,8 @@ async function sendSingleEmail(params, executive, personaTokens) {
416
491
  if (response.status === 401) {
417
492
  console.log('🔄 Access token expired, refreshing...');
418
493
  // Refresh the access token
419
- const clientId = fraim_config_1.fraimConfig.defaultOAuthClientId || process.env.FRAIM_DEFAULT_OAUTH_CLIENT_ID || process.env.PERSONA_DEFAULT_OAUTH_CLIENT_ID;
420
- const clientSecret = fraim_config_1.fraimConfig.defaultOAuthClientSecret || process.env.FRAIM_DEFAULT_OAUTH_CLIENT_SECRET || process.env.PERSONA_DEFAULT_OAUTH_CLIENT_SECRET;
494
+ const clientId = fraimConfig.defaultOAuthClientId || process.env.FRAIM_DEFAULT_OAUTH_CLIENT_ID || process.env.PERSONA_DEFAULT_OAUTH_CLIENT_ID;
495
+ const clientSecret = fraimConfig.defaultOAuthClientSecret || process.env.FRAIM_DEFAULT_OAUTH_CLIENT_SECRET || process.env.PERSONA_DEFAULT_OAUTH_CLIENT_SECRET;
421
496
  if (!clientId || !clientSecret) {
422
497
  throw new Error('FRAIM_DEFAULT_OAUTH_CLIENT_ID and FRAIM_DEFAULT_OAUTH_CLIENT_SECRET environment variables are required for token refresh');
423
498
  }
@@ -476,9 +551,9 @@ function generateHtmlEmail(params) {
476
551
  // Replace simple template variables
477
552
  template = template.replace(/\{\{displayName\}\}/g, escapeHtml(params.displayName));
478
553
  template = template.replace(/\{\{executiveName\}\}/g, escapeHtml(params.executiveName));
479
- template = template.replace(/\{\{personaName\}\}/g, escapeHtml(fraim_config_1.fraimConfig.personaName));
480
- template = template.replace(/\{\{chatUrl\}\}/g, escapeHtml(fraim_config_1.fraimConfig.chatUrl || '#'));
481
- template = template.replace(/\{\{webAppUrl\}\}/g, escapeHtml(fraim_config_1.fraimConfig.webAppUrl || '#'));
554
+ template = template.replace(/\{\{personaName\}\}/g, escapeHtml(fraimConfig.personaName));
555
+ template = template.replace(/\{\{chatUrl\}\}/g, escapeHtml(fraimConfig.chatUrl || '#'));
556
+ template = template.replace(/\{\{webAppUrl\}\}/g, escapeHtml(fraimConfig.webAppUrl || '#'));
482
557
  template = template.replace(/\{\{fromEmail\}\}/g, escapeHtml(params.fromEmail));
483
558
  template = template.replace(/\{\{greeting\}\}/g, escapeHtml(params.greeting));
484
559
  template = template.replace(/\{\{opening\}\}/g, params.opening);
@@ -495,16 +570,16 @@ function generateHtmlEmail(params) {
495
570
  html += `</div>`;
496
571
  return html;
497
572
  }).join('');
498
- const improvementsSection = `
499
- <tr>
500
- <td style="padding: 0 30px 20px 30px;">
501
- <div style="background-color: #f8f9fa; border-left: 4px solid #667eea; border-radius: 6px; padding: 20px; margin: 20px 0;">
502
- <div style="font-size: 18px; font-weight: 600; color: #333333; margin-bottom: 16px;">
503
- ✨ What's Fixed
504
- </div>
505
- ${improvementsHtml}
506
- </div>
507
- </td>
573
+ const improvementsSection = `
574
+ <tr>
575
+ <td style="padding: 0 30px 20px 30px;">
576
+ <div style="background-color: #f8f9fa; border-left: 4px solid #667eea; border-radius: 6px; padding: 20px; margin: 20px 0;">
577
+ <div style="font-size: 18px; font-weight: 600; color: #333333; margin-bottom: 16px;">
578
+ ✨ What's Fixed
579
+ </div>
580
+ ${improvementsHtml}
581
+ </div>
582
+ </td>
508
583
  </tr>`;
509
584
  template = template.replace(/\{\{#if hasImprovements\}\}[\s\S]*?\{\{\/if\}\}/, improvementsSection);
510
585
  }
@@ -514,13 +589,13 @@ function generateHtmlEmail(params) {
514
589
  }
515
590
  // Replace closing paragraph
516
591
  if (params.closing) {
517
- template = template.replace(/\{\{#if closing\}\}[\s\S]*?\{\{\/if\}\}/, `
518
- <tr>
519
- <td style="padding: 0 30px 20px 30px;">
520
- <div style="font-size: 16px; color: #555555; line-height: 1.8;">
521
- ${convertTextToHtml(params.closing)}
522
- </div>
523
- </td>
592
+ template = template.replace(/\{\{#if closing\}\}[\s\S]*?\{\{\/if\}\}/, `
593
+ <tr>
594
+ <td style="padding: 0 30px 20px 30px;">
595
+ <div style="font-size: 16px; color: #555555; line-height: 1.8;">
596
+ ${convertTextToHtml(params.closing)}
597
+ </div>
598
+ </td>
524
599
  </tr>`);
525
600
  }
526
601
  else {
@@ -548,7 +623,7 @@ function generatePlainTextBody(candidate) {
548
623
  if (candidate.closing) {
549
624
  body += `${candidate.closing}\n\n`;
550
625
  }
551
- body += (0, fraim_config_1.formatPersonaSignature)();
626
+ body += formatPersonaSignature();
552
627
  return body;
553
628
  }
554
629
  // Fallback to legacy body format
@@ -576,7 +651,7 @@ function extractFirstName(text) {
576
651
  function extractExecutiveName(displayName) {
577
652
  // "{Persona} - [Name]'s AI Executive Assistant"
578
653
  // We need to match based on the configured pattern
579
- const pattern = fraim_config_1.fraimConfig.personaDisplayNamePattern.replace('{executiveName}', '(.+?)');
654
+ const pattern = fraimConfig.personaDisplayNamePattern.replace('{executiveName}', '(.+?)');
580
655
  try {
581
656
  // If pattern contains regex characters, they need expanding or escaping?
582
657
  // This is simple pattern matching.