@wundam/orchex 1.0.0-rc.2 → 1.0.0-rc.21

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 (98) hide show
  1. package/README.md +59 -18
  2. package/dist/cloud-executor.d.ts +71 -0
  3. package/dist/cloud-executor.js +335 -0
  4. package/dist/cloud-sync.d.ts +8 -0
  5. package/dist/cloud-sync.js +52 -0
  6. package/dist/config.d.ts +30 -4
  7. package/dist/config.js +61 -2
  8. package/dist/context-builder.d.ts +2 -0
  9. package/dist/context-builder.js +11 -3
  10. package/dist/cost.js +1 -1
  11. package/dist/entitlements/jwt.d.ts +7 -0
  12. package/dist/entitlements/jwt.js +78 -0
  13. package/dist/entitlements/resolve.d.ts +17 -0
  14. package/dist/entitlements/resolve.js +49 -0
  15. package/dist/entitlements/types.d.ts +21 -0
  16. package/dist/entitlements/types.js +4 -0
  17. package/dist/executors/base.d.ts +1 -1
  18. package/dist/executors/bedrock-executor.d.ts +39 -0
  19. package/dist/executors/bedrock-executor.js +197 -0
  20. package/dist/executors/index.d.ts +1 -0
  21. package/dist/executors/index.js +24 -1
  22. package/dist/index.js +468 -23
  23. package/dist/intelligence/index.d.ts +44 -0
  24. package/dist/intelligence/index.js +160 -0
  25. package/dist/key-cache.d.ts +31 -0
  26. package/dist/key-cache.js +84 -0
  27. package/dist/login-helpers.d.ts +25 -0
  28. package/dist/login-helpers.js +54 -0
  29. package/dist/manifest.js +18 -1
  30. package/dist/mcp-instructions.d.ts +1 -0
  31. package/dist/mcp-instructions.js +84 -0
  32. package/dist/mcp-resources.d.ts +8 -0
  33. package/dist/mcp-resources.js +420 -0
  34. package/dist/model-cache.d.ts +18 -0
  35. package/dist/model-cache.js +62 -0
  36. package/dist/model-validator.d.ts +20 -0
  37. package/dist/model-validator.js +125 -0
  38. package/dist/orchestrator.d.ts +14 -0
  39. package/dist/orchestrator.js +191 -32
  40. package/dist/setup/ide-registry.d.ts +13 -0
  41. package/dist/setup/ide-registry.js +51 -0
  42. package/dist/setup/index.d.ts +1 -0
  43. package/dist/setup/index.js +111 -0
  44. package/dist/tier-gating.js +0 -16
  45. package/dist/tiers.d.ts +35 -5
  46. package/dist/tiers.js +39 -3
  47. package/dist/tools.d.ts +6 -1
  48. package/dist/tools.js +852 -95
  49. package/dist/types.d.ts +71 -60
  50. package/dist/types.js +3 -0
  51. package/dist/waves.d.ts +1 -1
  52. package/dist/waves.js +29 -2
  53. package/package.json +41 -5
  54. package/src/entitlements/public-key.pem +9 -0
  55. package/dist/intelligence/anti-pattern-detector.d.ts +0 -117
  56. package/dist/intelligence/anti-pattern-detector.js +0 -327
  57. package/dist/intelligence/budget-enforcer.d.ts +0 -119
  58. package/dist/intelligence/budget-enforcer.js +0 -226
  59. package/dist/intelligence/context-optimizer.d.ts +0 -111
  60. package/dist/intelligence/context-optimizer.js +0 -282
  61. package/dist/intelligence/cost-tracker.d.ts +0 -114
  62. package/dist/intelligence/cost-tracker.js +0 -183
  63. package/dist/intelligence/deliverable-extractor.d.ts +0 -134
  64. package/dist/intelligence/deliverable-extractor.js +0 -909
  65. package/dist/intelligence/dependency-inferrer.d.ts +0 -87
  66. package/dist/intelligence/dependency-inferrer.js +0 -403
  67. package/dist/intelligence/diagnostics.d.ts +0 -33
  68. package/dist/intelligence/diagnostics.js +0 -64
  69. package/dist/intelligence/error-analyzer.d.ts +0 -7
  70. package/dist/intelligence/error-analyzer.js +0 -76
  71. package/dist/intelligence/file-chunker.d.ts +0 -15
  72. package/dist/intelligence/file-chunker.js +0 -64
  73. package/dist/intelligence/fix-stream-manager.d.ts +0 -59
  74. package/dist/intelligence/fix-stream-manager.js +0 -212
  75. package/dist/intelligence/heuristics.d.ts +0 -23
  76. package/dist/intelligence/heuristics.js +0 -124
  77. package/dist/intelligence/learning-engine.d.ts +0 -157
  78. package/dist/intelligence/learning-engine.js +0 -433
  79. package/dist/intelligence/learning-feedback.d.ts +0 -96
  80. package/dist/intelligence/learning-feedback.js +0 -202
  81. package/dist/intelligence/pattern-analyzer.d.ts +0 -35
  82. package/dist/intelligence/pattern-analyzer.js +0 -189
  83. package/dist/intelligence/plan-parser.d.ts +0 -124
  84. package/dist/intelligence/plan-parser.js +0 -498
  85. package/dist/intelligence/planner.d.ts +0 -29
  86. package/dist/intelligence/planner.js +0 -86
  87. package/dist/intelligence/self-healer.d.ts +0 -16
  88. package/dist/intelligence/self-healer.js +0 -84
  89. package/dist/intelligence/slicing-metrics.d.ts +0 -62
  90. package/dist/intelligence/slicing-metrics.js +0 -202
  91. package/dist/intelligence/slicing-templates.d.ts +0 -81
  92. package/dist/intelligence/slicing-templates.js +0 -420
  93. package/dist/intelligence/split-suggester.d.ts +0 -69
  94. package/dist/intelligence/split-suggester.js +0 -176
  95. package/dist/intelligence/stream-generator.d.ts +0 -90
  96. package/dist/intelligence/stream-generator.js +0 -452
  97. package/dist/telemetry/telemetry-types.d.ts +0 -85
  98. package/dist/telemetry/telemetry-types.js +0 -1
package/dist/config.d.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  import { z } from 'zod';
2
2
  export declare const PRODUCTION_URL = "https://orchex.dev";
3
- export declare const LLMProviderSchema: z.ZodEnum<["anthropic", "openai", "gemini", "ollama", "deepseek"]>;
3
+ export declare const LLMProviderSchema: z.ZodEnum<["anthropic", "openai", "gemini", "ollama", "deepseek", "bedrock"]>;
4
4
  export type LLMProvider = z.infer<typeof LLMProviderSchema>;
5
5
  /**
6
6
  * Detect the LLM provider based on available environment variables.
7
7
  * Priority: ORCHEX_PROVIDER env var > first available API key
8
8
  */
9
9
  export declare function detectProvider(): LLMProvider;
10
+ /**
11
+ * Log the detected provider and masked key at startup.
12
+ */
13
+ export declare function logProviderDetection(): void;
10
14
  /**
11
15
  * Get the API key for a specific provider from environment variables.
12
16
  */
@@ -47,9 +51,13 @@ export declare const ConfigSchema: z.ZodObject<{
47
51
  /** User's subscription tier (synced from cloud on login) */
48
52
  tier: z.ZodDefault<z.ZodEnum<["free", "pro", "team", "enterprise"]>>;
49
53
  /** LLM provider (auto-detected if not set) */
50
- provider: z.ZodOptional<z.ZodEnum<["anthropic", "openai", "gemini", "ollama", "deepseek"]>>;
54
+ provider: z.ZodOptional<z.ZodEnum<["anthropic", "openai", "gemini", "ollama", "deepseek", "bedrock"]>>;
51
55
  /** LLM model (uses provider default if not set) */
52
56
  model: z.ZodOptional<z.ZodString>;
57
+ /** Cached trial runs remaining (synced from cloud on login) */
58
+ trialRunsRemaining: z.ZodOptional<z.ZodNumber>;
59
+ /** Account creation date (synced from cloud on login, ISO string) */
60
+ accountCreatedAt: z.ZodOptional<z.ZodString>;
53
61
  telemetry: z.ZodDefault<z.ZodObject<{
54
62
  enabled: z.ZodDefault<z.ZodBoolean>;
55
63
  endpoint: z.ZodOptional<z.ZodString>;
@@ -68,16 +76,20 @@ export declare const ConfigSchema: z.ZodObject<{
68
76
  enabled: boolean;
69
77
  endpoint?: string | undefined;
70
78
  };
71
- provider?: "anthropic" | "openai" | "gemini" | "ollama" | "deepseek" | undefined;
72
79
  apiKey?: string | undefined;
80
+ provider?: "anthropic" | "openai" | "gemini" | "ollama" | "deepseek" | "bedrock" | undefined;
73
81
  model?: string | undefined;
82
+ trialRunsRemaining?: number | undefined;
83
+ accountCreatedAt?: string | undefined;
74
84
  }, {
75
- provider?: "anthropic" | "openai" | "gemini" | "ollama" | "deepseek" | undefined;
76
85
  apiKey?: string | undefined;
86
+ provider?: "anthropic" | "openai" | "gemini" | "ollama" | "deepseek" | "bedrock" | undefined;
77
87
  mode?: "local" | "cloud" | undefined;
78
88
  apiUrl?: string | undefined;
79
89
  tier?: "free" | "pro" | "team" | "enterprise" | undefined;
80
90
  model?: string | undefined;
91
+ trialRunsRemaining?: number | undefined;
92
+ accountCreatedAt?: string | undefined;
81
93
  telemetry?: {
82
94
  enabled?: boolean | undefined;
83
95
  endpoint?: string | undefined;
@@ -90,6 +102,12 @@ export type TelemetryConfig = z.infer<typeof TelemetryConfigSchema>;
90
102
  * Returns error message if invalid, undefined if valid.
91
103
  */
92
104
  export declare function validateCloudConfig(config: Config): string | undefined;
105
+ /**
106
+ * Validate that cloud mode provider is compatible.
107
+ * Cloud execution currently only supports Anthropic.
108
+ * Returns error message if invalid, undefined if valid.
109
+ */
110
+ export declare function validateCloudProvider(config: Pick<Config, 'mode' | 'provider'>): string | undefined;
93
111
  /**
94
112
  * Load config from disk. Returns defaults when file doesn't exist.
95
113
  */
@@ -102,3 +120,11 @@ export declare function saveConfig(partial: Partial<Config>): Promise<Config>;
102
120
  * Returns config with apiKey masked for safe display (CLI output, logs).
103
121
  */
104
122
  export declare function maskConfigForDisplay(config: Config): Record<string, unknown>;
123
+ /**
124
+ * Resolve the API URL using priority order:
125
+ * 1. Explicit --api-url flag value
126
+ * 2. ORCHEX_API_URL environment variable
127
+ * 3. ORCHEX_STAGING_URL (deprecated — emits console.warn)
128
+ * 4. config.apiUrl from ~/.orchex/config.json (defaults to PRODUCTION_URL)
129
+ */
130
+ export declare function resolveApiUrl(flagValue?: string): Promise<string>;
package/dist/config.js CHANGED
@@ -3,12 +3,14 @@ import * as path from 'path';
3
3
  import * as os from 'os';
4
4
  import { z } from 'zod';
5
5
  import { TierIdSchema } from './tiers.js';
6
+ import { createLogger } from './logging.js';
7
+ const log = createLogger('config');
6
8
  // Well-known URLs
7
9
  export const PRODUCTION_URL = 'https://orchex.dev';
8
10
  // ============================================================================
9
11
  // LLM Provider Configuration
10
12
  // ============================================================================
11
- export const LLMProviderSchema = z.enum(['anthropic', 'openai', 'gemini', 'ollama', 'deepseek']);
13
+ export const LLMProviderSchema = z.enum(['anthropic', 'openai', 'gemini', 'ollama', 'deepseek', 'bedrock']);
12
14
  /**
13
15
  * Detect the LLM provider based on available environment variables.
14
16
  * Priority: ORCHEX_PROVIDER env var > first available API key
@@ -16,7 +18,7 @@ export const LLMProviderSchema = z.enum(['anthropic', 'openai', 'gemini', 'ollam
16
18
  export function detectProvider() {
17
19
  // Explicit provider override
18
20
  const explicit = process.env.ORCHEX_PROVIDER?.toLowerCase();
19
- if (explicit && ['anthropic', 'openai', 'gemini', 'ollama', 'deepseek'].includes(explicit)) {
21
+ if (explicit && ['anthropic', 'openai', 'gemini', 'ollama', 'deepseek', 'bedrock'].includes(explicit)) {
20
22
  return explicit;
21
23
  }
22
24
  // Auto-detect from available API keys (priority order)
@@ -28,11 +30,26 @@ export function detectProvider() {
28
30
  return 'gemini';
29
31
  if (process.env.DEEPSEEK_API_KEY)
30
32
  return 'deepseek';
33
+ if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY)
34
+ return 'bedrock';
31
35
  if (process.env.OLLAMA_BASE_URL || process.env.OLLAMA_HOST)
32
36
  return 'ollama';
33
37
  // Default to Anthropic (original behavior)
34
38
  return 'anthropic';
35
39
  }
40
+ function maskKey(key) {
41
+ if (key.length <= 8)
42
+ return '****';
43
+ return key.slice(0, 4) + '...' + key.slice(-4);
44
+ }
45
+ /**
46
+ * Log the detected provider and masked key at startup.
47
+ */
48
+ export function logProviderDetection() {
49
+ const provider = detectProvider();
50
+ const key = getProviderApiKey(provider);
51
+ log.info({ provider, key: key ? maskKey(key) : 'none' }, 'provider_detected');
52
+ }
36
53
  /**
37
54
  * Get the API key for a specific provider from environment variables.
38
55
  */
@@ -46,6 +63,8 @@ export function getProviderApiKey(provider) {
46
63
  return process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
47
64
  case 'deepseek':
48
65
  return process.env.DEEPSEEK_API_KEY;
66
+ case 'bedrock':
67
+ return undefined; // Bedrock uses AWS credentials, not API key
49
68
  case 'ollama':
50
69
  return undefined; // Ollama doesn't require an API key
51
70
  }
@@ -72,6 +91,7 @@ export const DEFAULT_MODELS = {
72
91
  openai: 'gpt-4.1',
73
92
  gemini: 'gemini-2.0-flash',
74
93
  deepseek: 'deepseek-coder',
94
+ bedrock: 'claude-3.5-sonnet',
75
95
  ollama: 'llama3.3:70b',
76
96
  };
77
97
  /**
@@ -125,6 +145,10 @@ export const ConfigSchema = z.object({
125
145
  provider: LLMProviderSchema.optional(),
126
146
  /** LLM model (uses provider default if not set) */
127
147
  model: z.string().optional(),
148
+ /** Cached trial runs remaining (synced from cloud on login) */
149
+ trialRunsRemaining: z.number().optional(),
150
+ /** Account creation date (synced from cloud on login, ISO string) */
151
+ accountCreatedAt: z.string().optional(),
128
152
  telemetry: TelemetryConfigSchema.default({ enabled: false }),
129
153
  });
130
154
  /**
@@ -137,6 +161,18 @@ export function validateCloudConfig(config) {
137
161
  }
138
162
  return undefined;
139
163
  }
164
+ /**
165
+ * Validate that cloud mode provider is compatible.
166
+ * Cloud execution currently only supports Anthropic.
167
+ * Returns error message if invalid, undefined if valid.
168
+ */
169
+ export function validateCloudProvider(config) {
170
+ if (config.mode !== 'cloud')
171
+ return undefined;
172
+ if (!config.provider || config.provider === 'anthropic')
173
+ return undefined;
174
+ return `Cloud mode currently only supports the Anthropic provider. Configured provider "${config.provider}" will be ignored by the cloud backend. Run: orchex config --provider anthropic`;
175
+ }
140
176
  function configDir() {
141
177
  return process.env.ORCHEX_CONFIG_DIR ?? path.join(os.homedir(), '.orchex');
142
178
  }
@@ -179,3 +215,26 @@ export function maskConfigForDisplay(config) {
179
215
  apiKey: config.apiKey ? '...' + config.apiKey.slice(-6) : undefined,
180
216
  };
181
217
  }
218
+ /**
219
+ * Resolve the API URL using priority order:
220
+ * 1. Explicit --api-url flag value
221
+ * 2. ORCHEX_API_URL environment variable
222
+ * 3. ORCHEX_STAGING_URL (deprecated — emits console.warn)
223
+ * 4. config.apiUrl from ~/.orchex/config.json (defaults to PRODUCTION_URL)
224
+ */
225
+ export async function resolveApiUrl(flagValue) {
226
+ // 1. Explicit flag (--api-url)
227
+ if (flagValue)
228
+ return flagValue;
229
+ // 2. Standard env var
230
+ if (process.env.ORCHEX_API_URL)
231
+ return process.env.ORCHEX_API_URL;
232
+ // 3. Deprecated env var — warn and use it
233
+ if (process.env.ORCHEX_STAGING_URL) {
234
+ console.warn('⚠ ORCHEX_STAGING_URL is deprecated. Use ORCHEX_API_URL instead.');
235
+ return process.env.ORCHEX_STAGING_URL;
236
+ }
237
+ // 4. Config file (defaults to PRODUCTION_URL if never set)
238
+ const config = await loadConfig();
239
+ return config.apiUrl;
240
+ }
@@ -31,6 +31,8 @@ export interface BuildPromptOptions {
31
31
  model?: string;
32
32
  /** Whether to enforce hard budget limits (throws ContextBudgetExceededError) */
33
33
  enforceHardLimit?: boolean;
34
+ /** Whether this is a fix stream (parentStreamId is set). When true, adds context about post-failure file state. */
35
+ isFixStream?: boolean;
34
36
  }
35
37
  /**
36
38
  * Build an optimized prompt with caching hints for cost reduction.
@@ -1,7 +1,6 @@
1
1
  import * as fs from 'fs/promises';
2
2
  import * as path from 'path';
3
- import { pruneUnusedFiles, estimateTokens, generateCachingHints } from './intelligence/context-optimizer.js';
4
- import { checkBudget, createBudgetConfig, ContextBudgetExceededError, } from './intelligence/budget-enforcer.js';
3
+ import { pruneUnusedFiles, estimateTokens, generateCachingHints, checkBudget, createBudgetConfig, ContextBudgetExceededError, } from './intelligence/index.js';
5
4
  const EXCLUDED_DIRS = new Set([
6
5
  'node_modules', '.git', 'dist', '.orchex', '.next',
7
6
  '__pycache__', '.cache', 'coverage', '.turbo',
@@ -322,7 +321,7 @@ async function readFileSafe(filePath) {
322
321
  // ============================================================================
323
322
  // Optimized Prompt Builder
324
323
  // ============================================================================
325
- import { extractRelevantChunks } from "./intelligence/file-chunker.js";
324
+ import { extractRelevantChunks } from "./intelligence/index.js";
326
325
  /**
327
326
  * Build an optimized prompt with caching hints for cost reduction.
328
327
  *
@@ -382,7 +381,16 @@ export async function buildFullPromptOptimized(projectDir, streamId, manifest, o
382
381
  // belong in taskContent, which all executors include in their messages.
383
382
  // IMPORTANT: buildInstructions() contains the orchex-artifact format spec.
384
383
  // Without it, LLMs won't produce parseable output.
384
+ const fixNote = options.isFixStream ? [
385
+ '',
386
+ '## Fix Stream Context',
387
+ '',
388
+ 'The files shown below reflect their CURRENT state on disk — after the previous failed attempt modified them.',
389
+ 'Your job is to fix the issues in these files.',
390
+ '',
391
+ ].join('\n') : '';
385
392
  const taskContent = [
393
+ fixNote,
386
394
  buildTaskContent(streamId, stream.name, stream.plan ?? '', manifest.feature, stream.owns ?? []),
387
395
  depsCtx,
388
396
  buildInstructions(streamId, stream.owns ?? [], options.provider),
package/dist/cost.js CHANGED
@@ -12,7 +12,7 @@ export const PROVIDER_RATES = {
12
12
  deepseek: { input: 0.00014, output: 0.0006 }, // Deepseek-VL
13
13
  ollama: { input: 0, output: 0 }, // Local, free
14
14
  };
15
- import { getModelCosts } from './intelligence/cost-tracker.js';
15
+ import { getModelCosts } from './intelligence/index.js';
16
16
  /**
17
17
  * Return LLM stream cost in USD for given input and output token counts.
18
18
  * If model is provided, use precise model-level rate. Otherwise, use provider-level fallback rates.
@@ -0,0 +1,7 @@
1
+ import { type Tier } from '../tiers.js';
2
+ import type { EntitlementClaims } from './types.js';
3
+ type SignableClaims = Omit<EntitlementClaims, 'iat' | 'exp'>;
4
+ export declare function signEntitlement(claims: SignableClaims, privateKeyPem: string, publicKeyPem: string, ttlOverride?: number): Promise<string>;
5
+ export declare function verifyEntitlement(jwt: string, publicKeyPem: string | string[]): Promise<EntitlementClaims | null>;
6
+ export declare function claimsToTier(claims: EntitlementClaims): Tier;
7
+ export {};
@@ -0,0 +1,78 @@
1
+ import { SignJWT, jwtVerify, importPKCS8, importSPKI } from 'jose';
2
+ import { createHash } from 'crypto';
3
+ import { getTier } from '../tiers.js';
4
+ import { JWT_TTL_SECONDS } from './types.js';
5
+ function computeKid(publicKeyPem) {
6
+ return createHash('sha256').update(publicKeyPem).digest('hex').slice(0, 8);
7
+ }
8
+ export async function signEntitlement(claims, privateKeyPem, publicKeyPem, ttlOverride) {
9
+ const privateKey = await importPKCS8(privateKeyPem, 'RS256');
10
+ const kid = computeKid(publicKeyPem);
11
+ const ttl = ttlOverride ?? JWT_TTL_SECONDS;
12
+ const payload = {
13
+ sub: claims.sub,
14
+ tier: claims.tier,
15
+ eff: claims.eff,
16
+ src: claims.src,
17
+ };
18
+ if (claims.promoId)
19
+ payload.promoId = claims.promoId;
20
+ if (ttl < 0) {
21
+ const now = Math.floor(Date.now() / 1000);
22
+ payload.iat = now + ttl - 1;
23
+ payload.exp = now + ttl;
24
+ return new SignJWT(payload)
25
+ .setProtectedHeader({ alg: 'RS256', kid })
26
+ .sign(privateKey);
27
+ }
28
+ return new SignJWT(payload)
29
+ .setProtectedHeader({ alg: 'RS256', kid })
30
+ .setIssuedAt()
31
+ .setExpirationTime(`${ttl}s`)
32
+ .sign(privateKey);
33
+ }
34
+ export async function verifyEntitlement(jwt, publicKeyPem) {
35
+ if (!jwt)
36
+ return null;
37
+ const pems = Array.isArray(publicKeyPem) ? publicKeyPem : [publicKeyPem];
38
+ let jwtKid;
39
+ try {
40
+ const headerB64 = jwt.split('.')[0];
41
+ const header = JSON.parse(Buffer.from(headerB64, 'base64url').toString());
42
+ jwtKid = header.kid;
43
+ }
44
+ catch { /* proceed without kid matching */ }
45
+ for (const pem of pems) {
46
+ if (jwtKid && pems.length > 1) {
47
+ const pemKid = computeKid(pem);
48
+ if (pemKid !== jwtKid)
49
+ continue;
50
+ }
51
+ try {
52
+ const publicKey = await importSPKI(pem, 'RS256');
53
+ const { payload } = await jwtVerify(jwt, publicKey);
54
+ return {
55
+ sub: payload.sub,
56
+ tier: payload.tier,
57
+ eff: payload.eff,
58
+ src: payload.src,
59
+ promoId: payload.promoId,
60
+ iat: payload.iat,
61
+ exp: payload.exp,
62
+ };
63
+ }
64
+ catch { /* try next key */ }
65
+ }
66
+ return null;
67
+ }
68
+ export function claimsToTier(claims) {
69
+ const base = getTier(claims.tier);
70
+ return {
71
+ ...base,
72
+ maxWaves: claims.eff.maxWaves,
73
+ maxParallelAgents: claims.eff.maxParallelAgents,
74
+ maxProviders: claims.eff.maxProviders,
75
+ maxApiTokens: claims.eff.maxApiTokens,
76
+ cloudOrchestrations: claims.eff.cloudOrchestrations,
77
+ };
78
+ }
@@ -0,0 +1,17 @@
1
+ import { type Tier } from '../tiers.js';
2
+ /**
3
+ * Load the embedded public key PEM.
4
+ * Tries multiple paths: dist (npm package), src (dev), env var override.
5
+ */
6
+ export declare function loadPublicKey(): Promise<string>;
7
+ /**
8
+ * Resolve the user's effective tier, preferring a cached JWT entitlement.
9
+ *
10
+ * 1. Try JWT entitlement (works for both local and cloud modes)
11
+ * 2. Fallback: resolve effective tier from config (includes trial→pro logic)
12
+ */
13
+ export declare function resolveEntitledTier(config: {
14
+ tier?: string;
15
+ accountCreatedAt?: string;
16
+ trialRunsRemaining?: number;
17
+ }, publicKeyPem: string): Promise<Tier>;
@@ -0,0 +1,49 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { getCachedEntitlement } from '../key-cache.js';
4
+ import { getTier, getEffectiveTier } from '../tiers.js';
5
+ import { claimsToTier } from './jwt.js';
6
+ let cachedPublicKey = null;
7
+ /**
8
+ * Load the embedded public key PEM.
9
+ * Tries multiple paths: dist (npm package), src (dev), env var override.
10
+ */
11
+ export async function loadPublicKey() {
12
+ if (cachedPublicKey)
13
+ return cachedPublicKey;
14
+ if (process.env.ENTITLEMENT_PUBLIC_KEY) {
15
+ cachedPublicKey = process.env.ENTITLEMENT_PUBLIC_KEY;
16
+ return cachedPublicKey;
17
+ }
18
+ const candidates = [
19
+ path.join(import.meta.dirname, 'public-key.pem'),
20
+ path.join(import.meta.dirname, '..', 'src', 'entitlements', 'public-key.pem'),
21
+ path.join(import.meta.dirname, '..', '..', 'src', 'entitlements', 'public-key.pem'),
22
+ ];
23
+ for (const p of candidates) {
24
+ try {
25
+ cachedPublicKey = await fs.readFile(p, 'utf-8');
26
+ return cachedPublicKey;
27
+ }
28
+ catch { /* try next */ }
29
+ }
30
+ throw new Error('Entitlement public key not found');
31
+ }
32
+ /**
33
+ * Resolve the user's effective tier, preferring a cached JWT entitlement.
34
+ *
35
+ * 1. Try JWT entitlement (works for both local and cloud modes)
36
+ * 2. Fallback: resolve effective tier from config (includes trial→pro logic)
37
+ */
38
+ export async function resolveEntitledTier(config, publicKeyPem) {
39
+ const claims = await getCachedEntitlement(publicKeyPem);
40
+ if (claims)
41
+ return claimsToTier(claims);
42
+ // Fallback: use effective tier (handles trial→pro resolution)
43
+ const effectiveTierId = getEffectiveTier({
44
+ tier: config.tier ?? 'free',
45
+ createdAt: config.accountCreatedAt ?? new Date(0).toISOString(),
46
+ trialRunsRemaining: config.trialRunsRemaining ?? 0,
47
+ });
48
+ return getTier(effectiveTierId);
49
+ }
@@ -0,0 +1,21 @@
1
+ import type { TierId } from '../tiers.js';
2
+ export type EntitlementSource = 'base' | 'trial' | 'fff' | 'internal' | 'beta' | 'boost';
3
+ export interface EntitlementClaims {
4
+ sub: string;
5
+ tier: TierId;
6
+ eff: {
7
+ maxWaves: number;
8
+ maxParallelAgents: number;
9
+ maxProviders: number;
10
+ maxApiTokens: number;
11
+ cloudOrchestrations: number;
12
+ };
13
+ src: EntitlementSource;
14
+ promoId?: string;
15
+ iat: number;
16
+ exp: number;
17
+ }
18
+ /** 'never' expiry maps to 100 years to avoid null handling. */
19
+ export declare const NEVER_EXPIRY_YEARS = 100;
20
+ /** JWT TTL in seconds — 24 hours. */
21
+ export declare const JWT_TTL_SECONDS: number;
@@ -0,0 +1,4 @@
1
+ /** 'never' expiry maps to 100 years to avoid null handling. */
2
+ export const NEVER_EXPIRY_YEARS = 100;
3
+ /** JWT TTL in seconds — 24 hours. */
4
+ export const JWT_TTL_SECONDS = 24 * 60 * 60;
@@ -91,7 +91,7 @@ export { Semaphore };
91
91
  * Default models for each provider.
92
92
  * Re-exported from config.ts for backward compatibility.
93
93
  */
94
- export declare const DEFAULT_MODELS: Record<"anthropic" | "openai" | "gemini" | "ollama" | "deepseek", string>;
94
+ export declare const DEFAULT_MODELS: Record<"anthropic" | "openai" | "gemini" | "ollama" | "deepseek" | "bedrock", string>;
95
95
  /**
96
96
  * Map a generic model name to provider-specific model.
97
97
  * Allows users to specify "claude-sonnet-4-5" and it gets translated appropriately.
@@ -0,0 +1,39 @@
1
+ /**
2
+ * AWS Bedrock Executor
3
+ *
4
+ * Supports Claude (via Bedrock), Llama, and Mistral models.
5
+ * Auth via AWS credentials (access key + secret key, or IAM role).
6
+ */
7
+ import type { ExecutorStrategy, ExecutionRequest, ExecutionResult } from '../types.js';
8
+ import { ExecutorConfig } from './base.js';
9
+ export declare function resolveBedrockModelId(model: string): string;
10
+ export interface BedrockExecutorConfig extends ExecutorConfig {
11
+ region: string;
12
+ accessKeyId?: string;
13
+ secretAccessKey?: string;
14
+ }
15
+ export interface BedrockClientLike {
16
+ invokeModel(params: {
17
+ modelId: string;
18
+ contentType: string;
19
+ accept: string;
20
+ body: string;
21
+ }): Promise<{
22
+ body: Uint8Array | string;
23
+ contentType?: string;
24
+ }>;
25
+ }
26
+ export declare class BedrockExecutor implements ExecutorStrategy {
27
+ readonly provider = "bedrock";
28
+ private config;
29
+ private semaphore;
30
+ private client?;
31
+ constructor(config?: Partial<BedrockExecutorConfig>, client?: BedrockClientLike);
32
+ private getClient;
33
+ execute(request: ExecutionRequest): Promise<ExecutionResult>;
34
+ private executeWithRetry;
35
+ private invokeWithTimeout;
36
+ private invokeModel;
37
+ private buildRequestBody;
38
+ private parseResponse;
39
+ }