outcome-cli 1.0.0

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 (113) hide show
  1. package/README.md +261 -0
  2. package/package.json +95 -0
  3. package/src/agents/README.md +139 -0
  4. package/src/agents/adapters/anthropic.adapter.ts +166 -0
  5. package/src/agents/adapters/dalle.adapter.ts +145 -0
  6. package/src/agents/adapters/gemini.adapter.ts +134 -0
  7. package/src/agents/adapters/imagen.adapter.ts +106 -0
  8. package/src/agents/adapters/nano-banana.adapter.ts +129 -0
  9. package/src/agents/adapters/openai.adapter.ts +165 -0
  10. package/src/agents/adapters/veo.adapter.ts +130 -0
  11. package/src/agents/agent.schema.property.test.ts +379 -0
  12. package/src/agents/agent.schema.test.ts +148 -0
  13. package/src/agents/agent.schema.ts +263 -0
  14. package/src/agents/index.ts +60 -0
  15. package/src/agents/registered-agent.schema.ts +356 -0
  16. package/src/agents/registry.ts +97 -0
  17. package/src/agents/tournament-configs.property.test.ts +266 -0
  18. package/src/cli/README.md +145 -0
  19. package/src/cli/commands/define.ts +79 -0
  20. package/src/cli/commands/list.ts +46 -0
  21. package/src/cli/commands/logs.ts +83 -0
  22. package/src/cli/commands/run.ts +416 -0
  23. package/src/cli/commands/verify.ts +110 -0
  24. package/src/cli/index.ts +81 -0
  25. package/src/config/README.md +128 -0
  26. package/src/config/env.ts +262 -0
  27. package/src/config/index.ts +19 -0
  28. package/src/eval/README.md +318 -0
  29. package/src/eval/ai-judge.test.ts +435 -0
  30. package/src/eval/ai-judge.ts +368 -0
  31. package/src/eval/code-validators.ts +414 -0
  32. package/src/eval/evaluateOutcome.property.test.ts +1174 -0
  33. package/src/eval/evaluateOutcome.ts +591 -0
  34. package/src/eval/immigration-validators.ts +122 -0
  35. package/src/eval/index.ts +90 -0
  36. package/src/eval/judge-cache.ts +402 -0
  37. package/src/eval/tournament-validators.property.test.ts +439 -0
  38. package/src/eval/validators.property.test.ts +1118 -0
  39. package/src/eval/validators.ts +1199 -0
  40. package/src/eval/weighted-scorer.ts +285 -0
  41. package/src/index.ts +17 -0
  42. package/src/league/README.md +188 -0
  43. package/src/league/health-check.ts +353 -0
  44. package/src/league/index.ts +93 -0
  45. package/src/league/killAgent.ts +151 -0
  46. package/src/league/league.test.ts +1151 -0
  47. package/src/league/runLeague.ts +843 -0
  48. package/src/league/scoreAgent.ts +175 -0
  49. package/src/modules/omnibridge/__tests__/.gitkeep +1 -0
  50. package/src/modules/omnibridge/__tests__/auth-tunnel.property.test.ts +524 -0
  51. package/src/modules/omnibridge/__tests__/deterministic-logger.property.test.ts +965 -0
  52. package/src/modules/omnibridge/__tests__/ghost-api.property.test.ts +461 -0
  53. package/src/modules/omnibridge/__tests__/omnibridge-integration.test.ts +542 -0
  54. package/src/modules/omnibridge/__tests__/parallel-executor.property.test.ts +671 -0
  55. package/src/modules/omnibridge/__tests__/semantic-normalizer.property.test.ts +521 -0
  56. package/src/modules/omnibridge/__tests__/semantic-normalizer.test.ts +254 -0
  57. package/src/modules/omnibridge/__tests__/session-vault.property.test.ts +367 -0
  58. package/src/modules/omnibridge/__tests__/shadow-session.property.test.ts +523 -0
  59. package/src/modules/omnibridge/__tests__/triangulation-engine.property.test.ts +292 -0
  60. package/src/modules/omnibridge/__tests__/verification-engine.property.test.ts +769 -0
  61. package/src/modules/omnibridge/api/.gitkeep +1 -0
  62. package/src/modules/omnibridge/api/ghost-api.ts +1087 -0
  63. package/src/modules/omnibridge/auth/.gitkeep +1 -0
  64. package/src/modules/omnibridge/auth/auth-tunnel.ts +843 -0
  65. package/src/modules/omnibridge/auth/session-vault.ts +577 -0
  66. package/src/modules/omnibridge/core/.gitkeep +1 -0
  67. package/src/modules/omnibridge/core/semantic-normalizer.ts +702 -0
  68. package/src/modules/omnibridge/core/triangulation-engine.ts +530 -0
  69. package/src/modules/omnibridge/core/types.ts +610 -0
  70. package/src/modules/omnibridge/execution/.gitkeep +1 -0
  71. package/src/modules/omnibridge/execution/deterministic-logger.ts +629 -0
  72. package/src/modules/omnibridge/execution/parallel-executor.ts +542 -0
  73. package/src/modules/omnibridge/execution/shadow-session.ts +794 -0
  74. package/src/modules/omnibridge/index.ts +212 -0
  75. package/src/modules/omnibridge/omnibridge.ts +510 -0
  76. package/src/modules/omnibridge/verification/.gitkeep +1 -0
  77. package/src/modules/omnibridge/verification/verification-engine.ts +783 -0
  78. package/src/outcomes/README.md +75 -0
  79. package/src/outcomes/acquire-pilot-customer.ts +297 -0
  80. package/src/outcomes/code-delivery-outcomes.ts +89 -0
  81. package/src/outcomes/code-outcomes.ts +256 -0
  82. package/src/outcomes/code_review_battle.test.ts +135 -0
  83. package/src/outcomes/code_review_battle.ts +135 -0
  84. package/src/outcomes/cold_email_battle.ts +97 -0
  85. package/src/outcomes/content_creation_battle.ts +160 -0
  86. package/src/outcomes/f1_stem_opt_compliance.ts +61 -0
  87. package/src/outcomes/index.ts +107 -0
  88. package/src/outcomes/lead_gen_battle.test.ts +113 -0
  89. package/src/outcomes/lead_gen_battle.ts +99 -0
  90. package/src/outcomes/outcome.schema.property.test.ts +229 -0
  91. package/src/outcomes/outcome.schema.ts +187 -0
  92. package/src/outcomes/qualified_sales_interest.ts +118 -0
  93. package/src/outcomes/swarm_planner.property.test.ts +370 -0
  94. package/src/outcomes/swarm_planner.ts +96 -0
  95. package/src/outcomes/web_extraction.ts +234 -0
  96. package/src/runtime/README.md +220 -0
  97. package/src/runtime/agentRunner.test.ts +341 -0
  98. package/src/runtime/agentRunner.ts +746 -0
  99. package/src/runtime/claudeAdapter.ts +232 -0
  100. package/src/runtime/costTracker.ts +123 -0
  101. package/src/runtime/index.ts +34 -0
  102. package/src/runtime/modelAdapter.property.test.ts +305 -0
  103. package/src/runtime/modelAdapter.ts +144 -0
  104. package/src/runtime/openaiAdapter.ts +235 -0
  105. package/src/utils/README.md +122 -0
  106. package/src/utils/command-runner.ts +134 -0
  107. package/src/utils/cost-guard.ts +379 -0
  108. package/src/utils/errors.test.ts +290 -0
  109. package/src/utils/errors.ts +442 -0
  110. package/src/utils/index.ts +37 -0
  111. package/src/utils/logger.test.ts +361 -0
  112. package/src/utils/logger.ts +419 -0
  113. package/src/utils/output-parsers.ts +216 -0
@@ -0,0 +1,128 @@
1
+ # Configuration Module
2
+
3
+ This module provides type-safe environment configuration with validation.
4
+
5
+ ## Overview
6
+
7
+ The configuration system:
8
+ - Validates all required environment variables on startup
9
+ - Fails fast in production if required API keys are missing
10
+ - Allows missing keys in development for easier local setup
11
+ - Provides type-safe access to configuration values
12
+
13
+ ## Required API Keys (Production)
14
+
15
+ The following API keys **must** be set for production deployment:
16
+
17
+ | Key | Description | Get it at |
18
+ |-----|-------------|-----------|
19
+ | `ANTHROPIC_API_KEY` | Anthropic Claude API | https://console.anthropic.com/ |
20
+ | `OPENAI_API_KEY` | OpenAI API | https://platform.openai.com/api-keys |
21
+ | `GOOGLE_API_KEY` | Google Gemini API | https://makersuite.google.com/app/apikey |
22
+ | `TREMENDOUS_API_KEY` | Tremendous (fiat payouts) | https://www.tremendous.com |
23
+ | `CIRCLE_API_KEY` | Circle USDC (crypto payouts) | https://console.circle.com |
24
+ | `CIRCLE_ENTITY_SECRET` | Circle entity secret | Run `npx @circle-fin/usdckit register-entity-secret` |
25
+ | `CIRCLE_TREASURY_ADDRESS` | Treasury wallet address | Run `npx tsx scripts/setup-circle-treasury.ts create` |
26
+ | `NEXT_PUBLIC_SUPABASE_URL` | Supabase project URL | https://supabase.com/dashboard |
27
+ | `NEXT_PUBLIC_SUPABASE_ANON_KEY` | Supabase anon key | https://supabase.com/dashboard |
28
+ | `SUPABASE_SERVICE_ROLE_KEY` | Supabase service role key | https://supabase.com/dashboard |
29
+
30
+ ## Usage
31
+
32
+ ```typescript
33
+ import { getEnvConfig, requireApiKey, hasApiKey, printEnvStatus } from './config';
34
+
35
+ // Get full config
36
+ const config = getEnvConfig();
37
+
38
+ // Check if a key is configured
39
+ if (hasApiKey('ANTHROPIC_API_KEY')) {
40
+ // Use Anthropic
41
+ }
42
+
43
+ // Get a required key (throws if missing)
44
+ const apiKey = requireApiKey('OPENAI_API_KEY');
45
+
46
+ // Print status for debugging
47
+ printEnvStatus();
48
+ ```
49
+
50
+ ## Local Development
51
+
52
+ 1. Copy `.env.example` to `.env`:
53
+ ```bash
54
+ cp .env.example .env
55
+ ```
56
+
57
+ 2. Fill in the API keys you need for development
58
+
59
+ 3. Missing keys are allowed in development mode
60
+
61
+ ## Cloudflare Workers Deployment
62
+
63
+ For Cloudflare Workers, use `wrangler secret` to set secrets:
64
+
65
+ ```bash
66
+ # Set secrets for default environment
67
+ wrangler secret put ANTHROPIC_API_KEY
68
+ wrangler secret put OPENAI_API_KEY
69
+ wrangler secret put GOOGLE_API_KEY
70
+ wrangler secret put TREMENDOUS_API_KEY
71
+ wrangler secret put CIRCLE_API_KEY
72
+ wrangler secret put CIRCLE_ENTITY_SECRET
73
+ wrangler secret put SUPABASE_SERVICE_ROLE_KEY
74
+
75
+ # Set secrets for staging
76
+ wrangler secret put ANTHROPIC_API_KEY --env staging
77
+ # ... repeat for all secrets
78
+
79
+ # Set secrets for production
80
+ wrangler secret put ANTHROPIC_API_KEY --env production
81
+ # ... repeat for all secrets
82
+
83
+ # List secrets
84
+ wrangler secret list
85
+ wrangler secret list --env production
86
+
87
+ # Delete a secret
88
+ wrangler secret delete SECRET_NAME
89
+ ```
90
+
91
+ ## Environment Modes
92
+
93
+ | Mode | Behavior |
94
+ |------|----------|
95
+ | `development` | Missing keys allowed, uses sandbox/testnet |
96
+ | `staging` | Missing keys allowed, uses sandbox/testnet |
97
+ | `production` | All required keys must be set, uses production APIs |
98
+
99
+ ## Payout Provider Modes
100
+
101
+ Control sandbox/production mode for payout providers:
102
+
103
+ ```bash
104
+ # Sandbox mode (default in development)
105
+ TREMENDOUS_SANDBOX=true
106
+ CIRCLE_TESTNET=true
107
+
108
+ # Production mode
109
+ TREMENDOUS_SANDBOX=false
110
+ CIRCLE_TESTNET=false
111
+ ```
112
+
113
+ ## Validation
114
+
115
+ The system validates environment variables on startup:
116
+
117
+ - **Production**: Fails with clear error message listing missing keys
118
+ - **Development**: Logs warnings but continues
119
+
120
+ Example error in production:
121
+ ```
122
+ Environment validation failed in production mode.
123
+ Missing required API keys:
124
+ - ANTHROPIC_API_KEY
125
+ - TREMENDOUS_API_KEY
126
+
127
+ Set these environment variables or use Cloudflare Workers secrets.
128
+ ```
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Environment Configuration Module
3
+ *
4
+ * Validates and provides type-safe access to environment variables.
5
+ * Fails fast with clear error messages when required variables are missing.
6
+ *
7
+ * Requirements: 9.1, 9.3, 9.4
8
+ */
9
+
10
+ import { z } from 'zod';
11
+
12
+ /**
13
+ * Schema for required environment variables in production
14
+ */
15
+ const productionRequiredSchema = z.object({
16
+ // AI Model Providers
17
+ ANTHROPIC_API_KEY: z.string().min(1, 'ANTHROPIC_API_KEY is required'),
18
+ OPENAI_API_KEY: z.string().min(1, 'OPENAI_API_KEY is required'),
19
+ GOOGLE_API_KEY: z.string().min(1, 'GOOGLE_API_KEY is required'),
20
+
21
+ // Payout Providers
22
+ TREMENDOUS_API_KEY: z.string().min(1, 'TREMENDOUS_API_KEY is required'),
23
+ CIRCLE_API_KEY: z.string().min(1, 'CIRCLE_API_KEY is required'),
24
+ CIRCLE_ENTITY_SECRET: z.string().min(1, 'CIRCLE_ENTITY_SECRET is required'),
25
+
26
+ // Authentication (Supabase)
27
+ NEXT_PUBLIC_SUPABASE_URL: z.string().min(1, 'NEXT_PUBLIC_SUPABASE_URL is required'),
28
+ NEXT_PUBLIC_SUPABASE_ANON_KEY: z.string().min(1, 'NEXT_PUBLIC_SUPABASE_ANON_KEY is required'),
29
+ SUPABASE_SERVICE_ROLE_KEY: z.string().min(1, 'SUPABASE_SERVICE_ROLE_KEY is required'),
30
+ });
31
+
32
+ /**
33
+ * Schema for optional environment variables
34
+ */
35
+ const optionalSchema = z.object({
36
+ // Environment mode
37
+ NODE_ENV: z.enum(['development', 'staging', 'production']).default('development'),
38
+ ENVIRONMENT: z.enum(['development', 'staging', 'production']).default('development'),
39
+
40
+ // Payout provider modes
41
+ TREMENDOUS_SANDBOX: z.string().transform(v => v === 'true').default('true'),
42
+ CIRCLE_TESTNET: z.string().transform(v => v === 'true').default('true'),
43
+
44
+ // Email (SendGrid)
45
+ SENDGRID_API_KEY: z.string().optional(),
46
+ SENDGRID_FROM_EMAIL: z.string().email().optional(),
47
+ SENDGRID_FROM_NAME: z.string().optional(),
48
+
49
+ // Notion Integration
50
+ NOTION_API_KEY: z.string().optional(),
51
+ NOTION_BRIEFINGS_DB: z.string().optional(),
52
+ NOTION_ACTIVITY_DB: z.string().optional(),
53
+ NOTION_SPONSORS_DB: z.string().optional(),
54
+ NOTION_TOURNAMENTS_DB: z.string().optional(),
55
+ NOTION_FEEDBACK_DB: z.string().optional(),
56
+ NOTION_CONTENT_DB: z.string().optional(),
57
+
58
+ // Google Integration
59
+ GOOGLE_SERVICE_ACCOUNT_PATH: z.string().optional(),
60
+ GOOGLE_METRICS_SHEET: z.string().optional(),
61
+ GOOGLE_SPONSORS_SHEET: z.string().optional(),
62
+ GOOGLE_TOURNAMENTS_SHEET: z.string().optional(),
63
+ GOOGLE_USERS_SHEET: z.string().optional(),
64
+ GOOGLE_CONTENT_SHEET: z.string().optional(),
65
+
66
+ // Slack Integration
67
+ SLACK_BOT_TOKEN: z.string().optional(),
68
+ SLACK_ALERTS_CHANNEL: z.string().optional(),
69
+ SLACK_BRIEFINGS_CHANNEL: z.string().optional(),
70
+ SLACK_TOURNAMENTS_CHANNEL: z.string().optional(),
71
+ SLACK_SPONSORS_CHANNEL: z.string().optional(),
72
+ SLACK_SUPPORT_CHANNEL: z.string().optional(),
73
+ SLACK_MARKETING_CHANNEL: z.string().optional(),
74
+
75
+ // Discord Bot
76
+ DISCORD_BOT_TOKEN: z.string().optional(),
77
+ DISCORD_GUILD_ID: z.string().optional(),
78
+
79
+ // Local Models (Ollama)
80
+ OLLAMA_BASE_URL: z.string().url().default('http://localhost:11434'),
81
+
82
+ // Infrastructure
83
+ MAX_AGENTS_PER_LEAGUE: z.string().transform(Number).default('10'),
84
+ GLOBAL_SPEND_CEILING: z.string().transform(Number).default('100000'),
85
+ });
86
+
87
+ /**
88
+ * Development schema - all required fields are optional
89
+ */
90
+ const developmentSchema = z.object({
91
+ ANTHROPIC_API_KEY: z.string().optional(),
92
+ OPENAI_API_KEY: z.string().optional(),
93
+ GOOGLE_API_KEY: z.string().optional(),
94
+ TREMENDOUS_API_KEY: z.string().optional(),
95
+ CIRCLE_API_KEY: z.string().optional(),
96
+ CIRCLE_ENTITY_SECRET: z.string().optional(),
97
+ NEXT_PUBLIC_SUPABASE_URL: z.string().optional(),
98
+ NEXT_PUBLIC_SUPABASE_ANON_KEY: z.string().optional(),
99
+ SUPABASE_SERVICE_ROLE_KEY: z.string().optional(),
100
+ }).merge(optionalSchema);
101
+
102
+ /**
103
+ * Full environment schema combining required and optional
104
+ */
105
+ const fullSchema = productionRequiredSchema.merge(optionalSchema);
106
+
107
+ export type EnvConfig = z.infer<typeof fullSchema>;
108
+ export type DevEnvConfig = z.infer<typeof developmentSchema>;
109
+
110
+ /**
111
+ * Validation error with details about missing keys
112
+ */
113
+ export class EnvValidationError extends Error {
114
+ constructor(
115
+ message: string,
116
+ public readonly missingKeys: string[],
117
+ public readonly details: z.ZodError
118
+ ) {
119
+ super(message);
120
+ this.name = 'EnvValidationError';
121
+ }
122
+ }
123
+
124
+
125
+ /**
126
+ * Determines if we're in production mode
127
+ */
128
+ function isProduction(): boolean {
129
+ const env = process.env.NODE_ENV || process.env.ENVIRONMENT || 'development';
130
+ return env === 'production';
131
+ }
132
+
133
+ /**
134
+ * Validates environment variables based on current mode.
135
+ * In production, all required API keys must be set.
136
+ * In development/staging, missing keys are allowed.
137
+ *
138
+ * @throws EnvValidationError if validation fails in production
139
+ */
140
+ export function validateEnv(): EnvConfig | DevEnvConfig {
141
+ const isProd = isProduction();
142
+
143
+ if (isProd) {
144
+ const result = fullSchema.safeParse(process.env);
145
+
146
+ if (!result.success) {
147
+ const missingKeys = result.error.issues
148
+ .filter(issue => issue.code === 'invalid_type' || issue.code === 'too_small')
149
+ .map(issue => issue.path.join('.'));
150
+
151
+ const errorMessage = [
152
+ 'Environment validation failed in production mode.',
153
+ 'Missing required API keys:',
154
+ ...missingKeys.map(key => ` - ${key}`),
155
+ '',
156
+ 'Set these environment variables or use Cloudflare Workers secrets.',
157
+ ].join('\n');
158
+
159
+ throw new EnvValidationError(errorMessage, missingKeys, result.error);
160
+ }
161
+
162
+ return result.data;
163
+ }
164
+
165
+ // Development mode - use relaxed schema
166
+ const result = developmentSchema.safeParse(process.env);
167
+
168
+ if (!result.success) {
169
+ // Log warnings but don't fail in development
170
+ console.warn('[env] Some environment variables are invalid:', result.error.format());
171
+ }
172
+
173
+ return result.data ?? ({} as DevEnvConfig);
174
+ }
175
+
176
+ /**
177
+ * Gets a validated environment configuration.
178
+ * Caches the result after first validation.
179
+ */
180
+ let cachedConfig: EnvConfig | DevEnvConfig | null = null;
181
+
182
+ export function getEnvConfig(): EnvConfig | DevEnvConfig {
183
+ if (!cachedConfig) {
184
+ cachedConfig = validateEnv();
185
+ }
186
+ return cachedConfig;
187
+ }
188
+
189
+ /**
190
+ * Checks if a specific API key is configured
191
+ */
192
+ export function hasApiKey(key: keyof EnvConfig): boolean {
193
+ const config = getEnvConfig();
194
+ const value = config[key as keyof typeof config];
195
+ return typeof value === 'string' && value.length > 0;
196
+ }
197
+
198
+ /**
199
+ * Gets an API key, throwing if not configured
200
+ */
201
+ export function requireApiKey(key: keyof EnvConfig): string {
202
+ const config = getEnvConfig();
203
+ const value = config[key as keyof typeof config];
204
+
205
+ if (typeof value !== 'string' || value.length === 0) {
206
+ throw new Error(`Required API key not configured: ${key}`);
207
+ }
208
+
209
+ return value;
210
+ }
211
+
212
+ /**
213
+ * Checks if running in sandbox/testnet mode for payout providers
214
+ */
215
+ export function isPayoutSandbox(): boolean {
216
+ const config = getEnvConfig();
217
+ return config.TREMENDOUS_SANDBOX === true || config.CIRCLE_TESTNET === true;
218
+ }
219
+
220
+ /**
221
+ * Gets the current environment mode
222
+ */
223
+ export function getEnvironment(): 'development' | 'staging' | 'production' {
224
+ const config = getEnvConfig();
225
+ return config.ENVIRONMENT || config.NODE_ENV || 'development';
226
+ }
227
+
228
+ /**
229
+ * Lists all required API keys for production
230
+ */
231
+ export const REQUIRED_API_KEYS = [
232
+ 'ANTHROPIC_API_KEY',
233
+ 'OPENAI_API_KEY',
234
+ 'GOOGLE_API_KEY',
235
+ 'TREMENDOUS_API_KEY',
236
+ 'CIRCLE_API_KEY',
237
+ 'CIRCLE_ENTITY_SECRET',
238
+ 'NEXT_PUBLIC_SUPABASE_URL',
239
+ 'NEXT_PUBLIC_SUPABASE_ANON_KEY',
240
+ 'SUPABASE_SERVICE_ROLE_KEY',
241
+ ] as const;
242
+
243
+ /**
244
+ * Prints environment status (for debugging)
245
+ */
246
+ export function printEnvStatus(): void {
247
+ // Ensure config is loaded
248
+ getEnvConfig();
249
+ const env = getEnvironment();
250
+
251
+ console.log(`\n[env] Environment: ${env}`);
252
+ console.log('[env] API Key Status:');
253
+
254
+ for (const key of REQUIRED_API_KEYS) {
255
+ const keyConfigured = hasApiKey(key);
256
+ const status = keyConfigured ? '✓' : '✗';
257
+ console.log(` ${status} ${key}`);
258
+ }
259
+
260
+ console.log(`[env] Payout Mode: ${isPayoutSandbox() ? 'Sandbox/Testnet' : 'Production'}`);
261
+ console.log('');
262
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Configuration Module
3
+ *
4
+ * Exports environment configuration utilities.
5
+ */
6
+
7
+ export {
8
+ validateEnv,
9
+ getEnvConfig,
10
+ hasApiKey,
11
+ requireApiKey,
12
+ isPayoutSandbox,
13
+ getEnvironment,
14
+ printEnvStatus,
15
+ REQUIRED_API_KEYS,
16
+ EnvValidationError,
17
+ type EnvConfig,
18
+ type DevEnvConfig,
19
+ } from './env.js';