@a3t/rapid-core 0.1.4 → 0.1.5
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/index.d.ts +201 -1
- package/dist/index.js +400 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -72,7 +72,21 @@ interface McpConfig {
|
|
|
72
72
|
servers?: Record<string, McpServerConfig>;
|
|
73
73
|
}
|
|
74
74
|
interface McpServerConfig {
|
|
75
|
+
/** Enable this MCP server (default: true) */
|
|
75
76
|
enabled?: boolean;
|
|
77
|
+
/** Server type: remote HTTP or local stdio */
|
|
78
|
+
type?: 'remote' | 'stdio';
|
|
79
|
+
/** URL for remote servers */
|
|
80
|
+
url?: string;
|
|
81
|
+
/** HTTP headers for remote servers */
|
|
82
|
+
headers?: Record<string, string>;
|
|
83
|
+
/** Command for stdio servers */
|
|
84
|
+
command?: string;
|
|
85
|
+
/** Arguments for stdio command */
|
|
86
|
+
args?: string[];
|
|
87
|
+
/** Environment variables for stdio servers */
|
|
88
|
+
env?: Record<string, string>;
|
|
89
|
+
/** Additional server-specific configuration */
|
|
76
90
|
[key: string]: unknown;
|
|
77
91
|
}
|
|
78
92
|
/**
|
|
@@ -420,4 +434,190 @@ declare function getAuthEnvironment(config?: ExternalAuthConfig): Promise<Record
|
|
|
420
434
|
*/
|
|
421
435
|
declare function formatAuthStatus(status: AuthStatus): string;
|
|
422
436
|
|
|
423
|
-
|
|
437
|
+
/**
|
|
438
|
+
* Built-in MCP Server Templates
|
|
439
|
+
*
|
|
440
|
+
* Predefined configurations for popular MCP servers that can be
|
|
441
|
+
* selected during `rapid init` or added via `rapid mcp add`.
|
|
442
|
+
*/
|
|
443
|
+
/**
|
|
444
|
+
* MCP server template definition
|
|
445
|
+
*/
|
|
446
|
+
interface McpServerTemplate {
|
|
447
|
+
/** Display name */
|
|
448
|
+
name: string;
|
|
449
|
+
/** Short description */
|
|
450
|
+
description: string;
|
|
451
|
+
/** Server type: remote HTTP or local stdio */
|
|
452
|
+
type: 'remote' | 'stdio';
|
|
453
|
+
/** URL for remote servers */
|
|
454
|
+
url?: string;
|
|
455
|
+
/** HTTP headers for remote servers (supports ${VAR} substitution) */
|
|
456
|
+
headers?: Record<string, string>;
|
|
457
|
+
/** Command for stdio servers */
|
|
458
|
+
command?: string;
|
|
459
|
+
/** Arguments for stdio command */
|
|
460
|
+
args?: string[];
|
|
461
|
+
/** Environment variables for stdio servers */
|
|
462
|
+
env?: Record<string, string>;
|
|
463
|
+
/** Required secrets (env var names) */
|
|
464
|
+
requiredSecrets: string[];
|
|
465
|
+
/** Hint for obtaining required secrets */
|
|
466
|
+
secretHint?: string;
|
|
467
|
+
/** Default 1Password reference for secrets */
|
|
468
|
+
secretReferences?: Record<string, string>;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Built-in MCP server templates
|
|
472
|
+
*/
|
|
473
|
+
declare const MCP_SERVER_TEMPLATES: Record<string, McpServerTemplate>;
|
|
474
|
+
/**
|
|
475
|
+
* Get a template by name
|
|
476
|
+
*/
|
|
477
|
+
declare function getMcpTemplate(name: string): McpServerTemplate | undefined;
|
|
478
|
+
/**
|
|
479
|
+
* Get all template names
|
|
480
|
+
*/
|
|
481
|
+
declare function getMcpTemplateNames(): string[];
|
|
482
|
+
/**
|
|
483
|
+
* Get templates that don't require secrets (easy setup)
|
|
484
|
+
*/
|
|
485
|
+
declare function getEasySetupTemplates(): string[];
|
|
486
|
+
/**
|
|
487
|
+
* Get all required secrets for a list of template names
|
|
488
|
+
*/
|
|
489
|
+
declare function getRequiredSecrets(templateNames: string[]): string[];
|
|
490
|
+
/**
|
|
491
|
+
* Get all secret references for a list of template names
|
|
492
|
+
*/
|
|
493
|
+
declare function getSecretReferences(templateNames: string[]): Record<string, string>;
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* MCP Server Management
|
|
497
|
+
*
|
|
498
|
+
* Functions for managing Model Context Protocol servers in RAPID configuration.
|
|
499
|
+
*/
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Extended MCP server configuration with type-safe properties
|
|
503
|
+
*/
|
|
504
|
+
interface McpServerDefinition extends McpServerConfig {
|
|
505
|
+
enabled?: boolean;
|
|
506
|
+
type?: 'remote' | 'stdio';
|
|
507
|
+
url?: string;
|
|
508
|
+
headers?: Record<string, string>;
|
|
509
|
+
command?: string;
|
|
510
|
+
args?: string[];
|
|
511
|
+
env?: Record<string, string>;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* MCP server info for display
|
|
515
|
+
*/
|
|
516
|
+
interface McpServerInfo {
|
|
517
|
+
name: string;
|
|
518
|
+
enabled: boolean;
|
|
519
|
+
type: 'remote' | 'stdio';
|
|
520
|
+
url?: string | undefined;
|
|
521
|
+
command?: string | undefined;
|
|
522
|
+
template?: string | undefined;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* MCP server status
|
|
526
|
+
*/
|
|
527
|
+
interface McpServerStatus extends McpServerInfo {
|
|
528
|
+
status: 'enabled' | 'disabled' | 'error';
|
|
529
|
+
error?: string | undefined;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Generated MCP config file format (for .mcp.json)
|
|
533
|
+
*/
|
|
534
|
+
interface GeneratedMcpConfig {
|
|
535
|
+
mcpServers: Record<string, McpServerEntry>;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Single server entry in generated config
|
|
539
|
+
*/
|
|
540
|
+
interface McpServerEntry {
|
|
541
|
+
type?: 'http' | 'stdio';
|
|
542
|
+
url?: string | undefined;
|
|
543
|
+
headers?: Record<string, string> | undefined;
|
|
544
|
+
command?: string | undefined;
|
|
545
|
+
args?: string[] | undefined;
|
|
546
|
+
env?: Record<string, string> | undefined;
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* OpenCode config format
|
|
550
|
+
*/
|
|
551
|
+
interface OpenCodeConfig {
|
|
552
|
+
$schema?: string;
|
|
553
|
+
mcp?: Record<string, OpenCodeMcpEntry>;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* OpenCode MCP entry format
|
|
557
|
+
*/
|
|
558
|
+
interface OpenCodeMcpEntry {
|
|
559
|
+
type: 'remote' | 'stdio';
|
|
560
|
+
url?: string | undefined;
|
|
561
|
+
headers?: Record<string, string> | undefined;
|
|
562
|
+
command?: string | undefined;
|
|
563
|
+
args?: string[] | undefined;
|
|
564
|
+
env?: Record<string, string> | undefined;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Get all configured MCP servers from config
|
|
568
|
+
*/
|
|
569
|
+
declare function getMcpServers(config: RapidConfig): McpServerInfo[];
|
|
570
|
+
/**
|
|
571
|
+
* Get MCP server status for all configured servers
|
|
572
|
+
*/
|
|
573
|
+
declare function getMcpServerStatus(config: RapidConfig): McpServerStatus[];
|
|
574
|
+
/**
|
|
575
|
+
* Add an MCP server to configuration
|
|
576
|
+
*/
|
|
577
|
+
declare function addMcpServer(config: RapidConfig, name: string, serverConfig: McpServerDefinition): RapidConfig;
|
|
578
|
+
/**
|
|
579
|
+
* Add an MCP server from a template
|
|
580
|
+
*/
|
|
581
|
+
declare function addMcpServerFromTemplate(config: RapidConfig, templateName: string): RapidConfig;
|
|
582
|
+
/**
|
|
583
|
+
* Remove an MCP server from configuration
|
|
584
|
+
*/
|
|
585
|
+
declare function removeMcpServer(config: RapidConfig, name: string): RapidConfig;
|
|
586
|
+
/**
|
|
587
|
+
* Enable an MCP server
|
|
588
|
+
*/
|
|
589
|
+
declare function enableMcpServer(config: RapidConfig, name: string): RapidConfig;
|
|
590
|
+
/**
|
|
591
|
+
* Disable an MCP server
|
|
592
|
+
*/
|
|
593
|
+
declare function disableMcpServer(config: RapidConfig, name: string): RapidConfig;
|
|
594
|
+
/**
|
|
595
|
+
* Generate .mcp.json config from rapid.json mcp section
|
|
596
|
+
*/
|
|
597
|
+
declare function generateMcpConfig(config: RapidConfig): GeneratedMcpConfig;
|
|
598
|
+
/**
|
|
599
|
+
* Generate opencode.json config format
|
|
600
|
+
*/
|
|
601
|
+
declare function generateOpenCodeConfig(config: RapidConfig): OpenCodeConfig;
|
|
602
|
+
/**
|
|
603
|
+
* Write .mcp.json file
|
|
604
|
+
*/
|
|
605
|
+
declare function writeMcpConfig(rootDir: string, config: RapidConfig): Promise<void>;
|
|
606
|
+
/**
|
|
607
|
+
* Write opencode.json file
|
|
608
|
+
*/
|
|
609
|
+
declare function writeOpenCodeConfig(rootDir: string, config: RapidConfig): Promise<void>;
|
|
610
|
+
/**
|
|
611
|
+
* Check if .mcp.json exists
|
|
612
|
+
*/
|
|
613
|
+
declare function hasMcpConfig(rootDir: string, config?: RapidConfig): Promise<boolean>;
|
|
614
|
+
/**
|
|
615
|
+
* Read existing .mcp.json file
|
|
616
|
+
*/
|
|
617
|
+
declare function readMcpConfig(rootDir: string, config?: RapidConfig): Promise<GeneratedMcpConfig | null>;
|
|
618
|
+
/**
|
|
619
|
+
* Get the MCP config file path for environment variable
|
|
620
|
+
*/
|
|
621
|
+
declare function getMcpConfigPath(rootDir: string, config?: RapidConfig): string;
|
|
622
|
+
|
|
623
|
+
export { type AgentDefinition, type AgentStatus, type AgentsConfig, type AuthStatus, type ContainerConfig, type ContainerStatus, type ContextConfig, type DetectedCredential, type DevcontainerConfig, type DotenvConfig, type EnvironmentStatus, type EnvrcConfig, type ExternalAuthConfig, type ExternalAuthSource, type GeneratedMcpConfig, type LoadedConfig, type LogLevel, MCP_SERVER_TEMPLATES, type McpConfig, type McpServerConfig, type McpServerDefinition, type McpServerEntry, type McpServerInfo, type McpServerStatus, type McpServerTemplate, type OpAuthStatus, type OpenCodeConfig, type OpenCodeMcpEntry, type RapidConfig, type SecretStatus, type SecretsConfig, type SecretsStatus, addMcpServer, addMcpServerFromTemplate, checkAgentAvailable, checkAllAgents, detectAiderAuth, detectAllCredentials, detectClaudeCodeAuth, detectCodexAuth, detectEnvAuth, detectGeminiAuth, disableMcpServer, enableMcpServer, execInContainer, formatAuthStatus, generateEnvrc, generateMcpConfig, generateOpenCodeConfig, getAgent, getAuthEnvironment, getAuthStatus, getContainerName, getContainerStatus, getCredentialsForProvider, getDefaultAgent, getDefaultConfig, getDevcontainerPath, getEasySetupTemplates, getLogLevel, getMcpConfigPath, getMcpServerStatus, getMcpServers, getMcpTemplate, getMcpTemplateNames, getOpAuthStatus, getProviderInfo, getRequiredSecrets, getSecretReferences, hasDevcontainerCli, hasDocker, hasEnvrc, hasMcpConfig, hasOpCli, hasOpServiceAccountToken, hasVaultCli, isOpAuthenticated, isVaultAuthenticated, launchAgent, loadConfig, loadConfigFromFile, loadDevcontainerConfig, loadSecrets, logger, mergeWithDefaults, readEnvrc, readMcpConfig, readOpSecret, readVaultSecret, removeMcpServer, setLogLevel, startContainer, stopContainer, verifySecret, verifySecrets, writeEnvrc, writeMcpConfig, writeOpenCodeConfig };
|
package/dist/index.js
CHANGED
|
@@ -1106,7 +1106,389 @@ function getProviderInfo(provider) {
|
|
|
1106
1106
|
};
|
|
1107
1107
|
}
|
|
1108
1108
|
}
|
|
1109
|
+
|
|
1110
|
+
// src/mcp.ts
|
|
1111
|
+
import { writeFile as writeFile2, readFile as readFile5, access as access3 } from "fs/promises";
|
|
1112
|
+
import { join as join4, isAbsolute } from "path";
|
|
1113
|
+
|
|
1114
|
+
// src/mcp-templates.ts
|
|
1115
|
+
var MCP_SERVER_TEMPLATES = {
|
|
1116
|
+
context7: {
|
|
1117
|
+
name: "Context7",
|
|
1118
|
+
description: "Documentation context for libraries and frameworks",
|
|
1119
|
+
type: "remote",
|
|
1120
|
+
url: "https://mcp.context7.com/mcp",
|
|
1121
|
+
headers: {
|
|
1122
|
+
"Context7-API-Key": "${CONTEXT7_API_KEY}"
|
|
1123
|
+
},
|
|
1124
|
+
requiredSecrets: ["CONTEXT7_API_KEY"],
|
|
1125
|
+
secretHint: "Get your API key at https://context7.com",
|
|
1126
|
+
secretReferences: {
|
|
1127
|
+
CONTEXT7_API_KEY: "op://Development/Context7/api-key"
|
|
1128
|
+
}
|
|
1129
|
+
},
|
|
1130
|
+
tavily: {
|
|
1131
|
+
name: "Tavily",
|
|
1132
|
+
description: "Web search and data extraction",
|
|
1133
|
+
type: "remote",
|
|
1134
|
+
url: "https://mcp.tavily.com/mcp",
|
|
1135
|
+
headers: {
|
|
1136
|
+
Authorization: "Bearer ${TAVILY_API_KEY}"
|
|
1137
|
+
},
|
|
1138
|
+
requiredSecrets: ["TAVILY_API_KEY"],
|
|
1139
|
+
secretHint: "Get your API key at https://tavily.com",
|
|
1140
|
+
secretReferences: {
|
|
1141
|
+
TAVILY_API_KEY: "op://Development/Tavily/api-key"
|
|
1142
|
+
}
|
|
1143
|
+
},
|
|
1144
|
+
playwright: {
|
|
1145
|
+
name: "Playwright",
|
|
1146
|
+
description: "Browser automation and web scraping",
|
|
1147
|
+
type: "stdio",
|
|
1148
|
+
command: "npx",
|
|
1149
|
+
args: ["@playwright/mcp@latest"],
|
|
1150
|
+
requiredSecrets: []
|
|
1151
|
+
},
|
|
1152
|
+
github: {
|
|
1153
|
+
name: "GitHub",
|
|
1154
|
+
description: "GitHub operations (PRs, issues, repos)",
|
|
1155
|
+
type: "stdio",
|
|
1156
|
+
command: "npx",
|
|
1157
|
+
args: ["@modelcontextprotocol/server-github"],
|
|
1158
|
+
env: {
|
|
1159
|
+
GITHUB_TOKEN: "${GITHUB_TOKEN}"
|
|
1160
|
+
},
|
|
1161
|
+
requiredSecrets: ["GITHUB_TOKEN"],
|
|
1162
|
+
secretHint: "Create a personal access token at https://github.com/settings/tokens",
|
|
1163
|
+
secretReferences: {
|
|
1164
|
+
GITHUB_TOKEN: "op://Development/GitHub/pat"
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
filesystem: {
|
|
1168
|
+
name: "Filesystem",
|
|
1169
|
+
description: "File system access (read/write/search)",
|
|
1170
|
+
type: "stdio",
|
|
1171
|
+
command: "npx",
|
|
1172
|
+
args: ["@modelcontextprotocol/server-filesystem", "."],
|
|
1173
|
+
requiredSecrets: []
|
|
1174
|
+
},
|
|
1175
|
+
memory: {
|
|
1176
|
+
name: "Memory",
|
|
1177
|
+
description: "Persistent knowledge graph memory",
|
|
1178
|
+
type: "stdio",
|
|
1179
|
+
command: "npx",
|
|
1180
|
+
args: ["@modelcontextprotocol/server-memory"],
|
|
1181
|
+
requiredSecrets: []
|
|
1182
|
+
},
|
|
1183
|
+
postgres: {
|
|
1184
|
+
name: "PostgreSQL",
|
|
1185
|
+
description: "PostgreSQL database access",
|
|
1186
|
+
type: "stdio",
|
|
1187
|
+
command: "npx",
|
|
1188
|
+
args: ["@modelcontextprotocol/server-postgres"],
|
|
1189
|
+
env: {
|
|
1190
|
+
DATABASE_URL: "${DATABASE_URL}"
|
|
1191
|
+
},
|
|
1192
|
+
requiredSecrets: ["DATABASE_URL"],
|
|
1193
|
+
secretHint: "PostgreSQL connection string (e.g., postgres://user:pass@host:5432/db)",
|
|
1194
|
+
secretReferences: {
|
|
1195
|
+
DATABASE_URL: "op://Development/PostgreSQL/connection-string"
|
|
1196
|
+
}
|
|
1197
|
+
},
|
|
1198
|
+
slack: {
|
|
1199
|
+
name: "Slack",
|
|
1200
|
+
description: "Slack messaging and channel management",
|
|
1201
|
+
type: "stdio",
|
|
1202
|
+
command: "npx",
|
|
1203
|
+
args: ["@modelcontextprotocol/server-slack"],
|
|
1204
|
+
env: {
|
|
1205
|
+
SLACK_TOKEN: "${SLACK_TOKEN}"
|
|
1206
|
+
},
|
|
1207
|
+
requiredSecrets: ["SLACK_TOKEN"],
|
|
1208
|
+
secretHint: "Create a Slack app and get a bot token at https://api.slack.com/apps",
|
|
1209
|
+
secretReferences: {
|
|
1210
|
+
SLACK_TOKEN: "op://Development/Slack/bot-token"
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
fetch: {
|
|
1214
|
+
name: "Fetch",
|
|
1215
|
+
description: "HTTP fetch for web content retrieval",
|
|
1216
|
+
type: "stdio",
|
|
1217
|
+
command: "npx",
|
|
1218
|
+
args: ["@modelcontextprotocol/server-fetch"],
|
|
1219
|
+
requiredSecrets: []
|
|
1220
|
+
},
|
|
1221
|
+
sqlite: {
|
|
1222
|
+
name: "SQLite",
|
|
1223
|
+
description: "SQLite database access",
|
|
1224
|
+
type: "stdio",
|
|
1225
|
+
command: "npx",
|
|
1226
|
+
args: ["@modelcontextprotocol/server-sqlite"],
|
|
1227
|
+
requiredSecrets: []
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
function getMcpTemplate(name) {
|
|
1231
|
+
return MCP_SERVER_TEMPLATES[name];
|
|
1232
|
+
}
|
|
1233
|
+
function getMcpTemplateNames() {
|
|
1234
|
+
return Object.keys(MCP_SERVER_TEMPLATES);
|
|
1235
|
+
}
|
|
1236
|
+
function getEasySetupTemplates() {
|
|
1237
|
+
return Object.entries(MCP_SERVER_TEMPLATES).filter(([, template]) => template.requiredSecrets.length === 0).map(([name]) => name);
|
|
1238
|
+
}
|
|
1239
|
+
function getRequiredSecrets(templateNames) {
|
|
1240
|
+
const secrets = /* @__PURE__ */ new Set();
|
|
1241
|
+
for (const name of templateNames) {
|
|
1242
|
+
const template = MCP_SERVER_TEMPLATES[name];
|
|
1243
|
+
if (template) {
|
|
1244
|
+
for (const secret of template.requiredSecrets) {
|
|
1245
|
+
secrets.add(secret);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
return [...secrets];
|
|
1250
|
+
}
|
|
1251
|
+
function getSecretReferences(templateNames) {
|
|
1252
|
+
const refs = {};
|
|
1253
|
+
for (const name of templateNames) {
|
|
1254
|
+
const template = MCP_SERVER_TEMPLATES[name];
|
|
1255
|
+
if (template?.secretReferences) {
|
|
1256
|
+
Object.assign(refs, template.secretReferences);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return refs;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// src/mcp.ts
|
|
1263
|
+
function getMcpServers(config) {
|
|
1264
|
+
const servers = [];
|
|
1265
|
+
if (!config.mcp?.servers) {
|
|
1266
|
+
return servers;
|
|
1267
|
+
}
|
|
1268
|
+
for (const [name, serverConfig] of Object.entries(config.mcp.servers)) {
|
|
1269
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
1270
|
+
continue;
|
|
1271
|
+
}
|
|
1272
|
+
const def = serverConfig;
|
|
1273
|
+
const template = getMcpTemplate(name);
|
|
1274
|
+
servers.push({
|
|
1275
|
+
name,
|
|
1276
|
+
enabled: def.enabled !== false,
|
|
1277
|
+
type: def.type ?? template?.type ?? "stdio",
|
|
1278
|
+
url: def.url ?? template?.url,
|
|
1279
|
+
command: def.command ?? template?.command,
|
|
1280
|
+
template: template ? name : void 0
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
return servers;
|
|
1284
|
+
}
|
|
1285
|
+
function getMcpServerStatus(config) {
|
|
1286
|
+
const servers = getMcpServers(config);
|
|
1287
|
+
return servers.map((server) => ({
|
|
1288
|
+
...server,
|
|
1289
|
+
status: server.enabled ? "enabled" : "disabled"
|
|
1290
|
+
}));
|
|
1291
|
+
}
|
|
1292
|
+
function addMcpServer(config, name, serverConfig) {
|
|
1293
|
+
return {
|
|
1294
|
+
...config,
|
|
1295
|
+
mcp: {
|
|
1296
|
+
...config.mcp,
|
|
1297
|
+
configFile: config.mcp?.configFile ?? ".mcp.json",
|
|
1298
|
+
servers: {
|
|
1299
|
+
...config.mcp?.servers,
|
|
1300
|
+
[name]: serverConfig
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
function addMcpServerFromTemplate(config, templateName) {
|
|
1306
|
+
const template = getMcpTemplate(templateName);
|
|
1307
|
+
if (!template) {
|
|
1308
|
+
throw new Error(`Unknown MCP server template: ${templateName}`);
|
|
1309
|
+
}
|
|
1310
|
+
const serverConfig = {
|
|
1311
|
+
enabled: true,
|
|
1312
|
+
type: template.type
|
|
1313
|
+
};
|
|
1314
|
+
if (template.type === "remote") {
|
|
1315
|
+
if (template.url) {
|
|
1316
|
+
serverConfig.url = template.url;
|
|
1317
|
+
}
|
|
1318
|
+
if (template.headers) {
|
|
1319
|
+
serverConfig.headers = { ...template.headers };
|
|
1320
|
+
}
|
|
1321
|
+
} else {
|
|
1322
|
+
if (template.command) {
|
|
1323
|
+
serverConfig.command = template.command;
|
|
1324
|
+
}
|
|
1325
|
+
if (template.args) {
|
|
1326
|
+
serverConfig.args = [...template.args];
|
|
1327
|
+
}
|
|
1328
|
+
if (template.env) {
|
|
1329
|
+
serverConfig.env = { ...template.env };
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
return addMcpServer(config, templateName, serverConfig);
|
|
1333
|
+
}
|
|
1334
|
+
function removeMcpServer(config, name) {
|
|
1335
|
+
if (!config.mcp?.servers?.[name]) {
|
|
1336
|
+
throw new Error(`MCP server not found: ${name}`);
|
|
1337
|
+
}
|
|
1338
|
+
const { [name]: _removed, ...remainingServers } = config.mcp.servers;
|
|
1339
|
+
return {
|
|
1340
|
+
...config,
|
|
1341
|
+
mcp: {
|
|
1342
|
+
...config.mcp,
|
|
1343
|
+
servers: remainingServers
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
function enableMcpServer(config, name) {
|
|
1348
|
+
if (!config.mcp?.servers?.[name]) {
|
|
1349
|
+
throw new Error(`MCP server not found: ${name}`);
|
|
1350
|
+
}
|
|
1351
|
+
return {
|
|
1352
|
+
...config,
|
|
1353
|
+
mcp: {
|
|
1354
|
+
...config.mcp,
|
|
1355
|
+
servers: {
|
|
1356
|
+
...config.mcp.servers,
|
|
1357
|
+
[name]: {
|
|
1358
|
+
...config.mcp.servers[name],
|
|
1359
|
+
enabled: true
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
};
|
|
1364
|
+
}
|
|
1365
|
+
function disableMcpServer(config, name) {
|
|
1366
|
+
if (!config.mcp?.servers?.[name]) {
|
|
1367
|
+
throw new Error(`MCP server not found: ${name}`);
|
|
1368
|
+
}
|
|
1369
|
+
return {
|
|
1370
|
+
...config,
|
|
1371
|
+
mcp: {
|
|
1372
|
+
...config.mcp,
|
|
1373
|
+
servers: {
|
|
1374
|
+
...config.mcp.servers,
|
|
1375
|
+
[name]: {
|
|
1376
|
+
...config.mcp.servers[name],
|
|
1377
|
+
enabled: false
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
function generateMcpConfig(config) {
|
|
1384
|
+
const mcpServers = {};
|
|
1385
|
+
if (!config.mcp?.servers) {
|
|
1386
|
+
return { mcpServers };
|
|
1387
|
+
}
|
|
1388
|
+
for (const [name, serverConfig] of Object.entries(config.mcp.servers)) {
|
|
1389
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
const def = serverConfig;
|
|
1393
|
+
if (def.enabled === false) {
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1396
|
+
const template = getMcpTemplate(name);
|
|
1397
|
+
const entry = {};
|
|
1398
|
+
const type = def.type ?? template?.type ?? "stdio";
|
|
1399
|
+
if (type === "remote") {
|
|
1400
|
+
entry.type = "http";
|
|
1401
|
+
entry.url = def.url ?? template?.url;
|
|
1402
|
+
entry.headers = def.headers ?? template?.headers;
|
|
1403
|
+
} else {
|
|
1404
|
+
entry.type = "stdio";
|
|
1405
|
+
entry.command = def.command ?? template?.command;
|
|
1406
|
+
entry.args = def.args ?? template?.args;
|
|
1407
|
+
if (def.env ?? template?.env) {
|
|
1408
|
+
entry.env = { ...template?.env, ...def.env };
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
mcpServers[name] = entry;
|
|
1412
|
+
}
|
|
1413
|
+
return { mcpServers };
|
|
1414
|
+
}
|
|
1415
|
+
function generateOpenCodeConfig(config) {
|
|
1416
|
+
const mcp = {};
|
|
1417
|
+
if (!config.mcp?.servers) {
|
|
1418
|
+
return { $schema: "https://opencode.ai/config.json", mcp };
|
|
1419
|
+
}
|
|
1420
|
+
for (const [name, serverConfig] of Object.entries(config.mcp.servers)) {
|
|
1421
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
1422
|
+
continue;
|
|
1423
|
+
}
|
|
1424
|
+
const def = serverConfig;
|
|
1425
|
+
if (def.enabled === false) {
|
|
1426
|
+
continue;
|
|
1427
|
+
}
|
|
1428
|
+
const template = getMcpTemplate(name);
|
|
1429
|
+
const type = def.type ?? template?.type ?? "stdio";
|
|
1430
|
+
const entry = {
|
|
1431
|
+
type
|
|
1432
|
+
};
|
|
1433
|
+
if (type === "remote") {
|
|
1434
|
+
entry.url = def.url ?? template?.url;
|
|
1435
|
+
const headers = def.headers ?? template?.headers;
|
|
1436
|
+
if (headers) {
|
|
1437
|
+
entry.headers = {};
|
|
1438
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1439
|
+
entry.headers[key] = value.replace(/\$\{(\w+)\}/g, "{env:$1}");
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
} else {
|
|
1443
|
+
entry.command = def.command ?? template?.command;
|
|
1444
|
+
entry.args = def.args ?? template?.args;
|
|
1445
|
+
if (def.env ?? template?.env) {
|
|
1446
|
+
entry.env = { ...template?.env, ...def.env };
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
mcp[name] = entry;
|
|
1450
|
+
}
|
|
1451
|
+
return { $schema: "https://opencode.ai/config.json", mcp };
|
|
1452
|
+
}
|
|
1453
|
+
async function writeMcpConfig(rootDir, config) {
|
|
1454
|
+
const mcpConfig = generateMcpConfig(config);
|
|
1455
|
+
const configFile = config.mcp?.configFile ?? ".mcp.json";
|
|
1456
|
+
const configPath = isAbsolute(configFile) ? configFile : join4(rootDir, configFile);
|
|
1457
|
+
await writeFile2(configPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
|
|
1458
|
+
}
|
|
1459
|
+
async function writeOpenCodeConfig(rootDir, config) {
|
|
1460
|
+
const openCodeConfig = generateOpenCodeConfig(config);
|
|
1461
|
+
const configPath = join4(rootDir, "opencode.json");
|
|
1462
|
+
await writeFile2(configPath, JSON.stringify(openCodeConfig, null, 2) + "\n", "utf-8");
|
|
1463
|
+
}
|
|
1464
|
+
async function hasMcpConfig(rootDir, config) {
|
|
1465
|
+
const configFile = config?.mcp?.configFile ?? ".mcp.json";
|
|
1466
|
+
const configPath = isAbsolute(configFile) ? configFile : join4(rootDir, configFile);
|
|
1467
|
+
try {
|
|
1468
|
+
await access3(configPath);
|
|
1469
|
+
return true;
|
|
1470
|
+
} catch {
|
|
1471
|
+
return false;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
async function readMcpConfig(rootDir, config) {
|
|
1475
|
+
const configFile = config?.mcp?.configFile ?? ".mcp.json";
|
|
1476
|
+
const configPath = isAbsolute(configFile) ? configFile : join4(rootDir, configFile);
|
|
1477
|
+
try {
|
|
1478
|
+
const content = await readFile5(configPath, "utf-8");
|
|
1479
|
+
return JSON.parse(content);
|
|
1480
|
+
} catch {
|
|
1481
|
+
return null;
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
function getMcpConfigPath(rootDir, config) {
|
|
1485
|
+
const configFile = config?.mcp?.configFile ?? ".mcp.json";
|
|
1486
|
+
return isAbsolute(configFile) ? configFile : join4(rootDir, configFile);
|
|
1487
|
+
}
|
|
1109
1488
|
export {
|
|
1489
|
+
MCP_SERVER_TEMPLATES,
|
|
1490
|
+
addMcpServer,
|
|
1491
|
+
addMcpServerFromTemplate,
|
|
1110
1492
|
checkAgentAvailable,
|
|
1111
1493
|
checkAllAgents,
|
|
1112
1494
|
detectAiderAuth,
|
|
@@ -1115,9 +1497,13 @@ export {
|
|
|
1115
1497
|
detectCodexAuth,
|
|
1116
1498
|
detectEnvAuth,
|
|
1117
1499
|
detectGeminiAuth,
|
|
1500
|
+
disableMcpServer,
|
|
1501
|
+
enableMcpServer,
|
|
1118
1502
|
execInContainer,
|
|
1119
1503
|
formatAuthStatus,
|
|
1120
1504
|
generateEnvrc,
|
|
1505
|
+
generateMcpConfig,
|
|
1506
|
+
generateOpenCodeConfig,
|
|
1121
1507
|
getAgent,
|
|
1122
1508
|
getAuthEnvironment,
|
|
1123
1509
|
getAuthStatus,
|
|
@@ -1127,12 +1513,21 @@ export {
|
|
|
1127
1513
|
getDefaultAgent,
|
|
1128
1514
|
getDefaultConfig,
|
|
1129
1515
|
getDevcontainerPath,
|
|
1516
|
+
getEasySetupTemplates,
|
|
1130
1517
|
getLogLevel,
|
|
1518
|
+
getMcpConfigPath,
|
|
1519
|
+
getMcpServerStatus,
|
|
1520
|
+
getMcpServers,
|
|
1521
|
+
getMcpTemplate,
|
|
1522
|
+
getMcpTemplateNames,
|
|
1131
1523
|
getOpAuthStatus,
|
|
1132
1524
|
getProviderInfo,
|
|
1525
|
+
getRequiredSecrets,
|
|
1526
|
+
getSecretReferences,
|
|
1133
1527
|
hasDevcontainerCli,
|
|
1134
1528
|
hasDocker,
|
|
1135
1529
|
hasEnvrc,
|
|
1530
|
+
hasMcpConfig,
|
|
1136
1531
|
hasOpCli,
|
|
1137
1532
|
hasOpServiceAccountToken,
|
|
1138
1533
|
hasVaultCli,
|
|
@@ -1146,13 +1541,17 @@ export {
|
|
|
1146
1541
|
logger,
|
|
1147
1542
|
mergeWithDefaults,
|
|
1148
1543
|
readEnvrc,
|
|
1544
|
+
readMcpConfig,
|
|
1149
1545
|
readOpSecret,
|
|
1150
1546
|
readVaultSecret,
|
|
1547
|
+
removeMcpServer,
|
|
1151
1548
|
setLogLevel,
|
|
1152
1549
|
startContainer,
|
|
1153
1550
|
stopContainer,
|
|
1154
1551
|
verifySecret,
|
|
1155
1552
|
verifySecrets,
|
|
1156
|
-
writeEnvrc
|
|
1553
|
+
writeEnvrc,
|
|
1554
|
+
writeMcpConfig,
|
|
1555
|
+
writeOpenCodeConfig
|
|
1157
1556
|
};
|
|
1158
1557
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/agents.ts","../src/external-auth.ts","../src/logger.ts","../src/container.ts","../src/secrets.ts"],"sourcesContent":["/**\n * Configuration loading and validation\n */\n\nimport { cosmiconfig } from 'cosmiconfig';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport type { RapidConfig } from './types.js';\n\nconst CONFIG_NAME = 'rapid';\nconst CONFIG_FILES = ['rapid.json', 'rapid.config.json', '.rapidrc', '.rapidrc.json'];\n\nexport interface LoadedConfig {\n config: RapidConfig;\n filepath: string;\n rootDir: string;\n}\n\n/**\n * Load RAPID configuration from the current directory or ancestors\n */\nexport async function loadConfig(cwd?: string): Promise<LoadedConfig | null> {\n const explorer = cosmiconfig(CONFIG_NAME, {\n searchPlaces: CONFIG_FILES,\n loaders: {\n '.json': async (filepath) => {\n const content = await readFile(filepath, 'utf-8');\n return JSON.parse(content);\n },\n },\n });\n\n const result = await explorer.search(cwd);\n\n if (!result || result.isEmpty) {\n return null;\n }\n\n return {\n config: result.config as RapidConfig,\n filepath: result.filepath,\n rootDir: dirname(result.filepath),\n };\n}\n\n/**\n * Load configuration from a specific file\n */\nexport async function loadConfigFromFile(filepath: string): Promise<LoadedConfig> {\n const content = await readFile(filepath, 'utf-8');\n const config = JSON.parse(content) as RapidConfig;\n\n return {\n config,\n filepath: resolve(filepath),\n rootDir: dirname(resolve(filepath)),\n };\n}\n\n/**\n * Get default configuration\n */\nexport function getDefaultConfig(): RapidConfig {\n return {\n version: '1.0',\n agents: {\n default: 'claude',\n available: {\n claude: {\n cli: 'claude',\n instructionFile: 'CLAUDE.md',\n envVars: ['ANTHROPIC_API_KEY'],\n },\n opencode: {\n cli: 'opencode',\n instructionFile: 'AGENTS.md',\n envVars: ['ANTHROPIC_API_KEY'],\n },\n aider: {\n cli: 'aider',\n instructionFile: 'AGENTS.md',\n envVars: ['ANTHROPIC_API_KEY'],\n args: ['--model', 'claude-3-5-sonnet-20241022'],\n },\n },\n },\n secrets: {\n provider: 'env',\n },\n context: {\n files: ['README.md'],\n dirs: ['docs/'],\n generateAgentFiles: true,\n },\n };\n}\n\n/**\n * Merge user config with defaults\n */\nexport function mergeWithDefaults(config: Partial<RapidConfig>): RapidConfig {\n const defaults = getDefaultConfig();\n\n return {\n ...defaults,\n ...config,\n agents: {\n ...defaults.agents,\n ...config.agents,\n available: {\n ...defaults.agents.available,\n ...config.agents?.available,\n },\n },\n secrets: {\n ...defaults.secrets,\n ...config.secrets,\n },\n context: {\n ...defaults.context,\n ...config.context,\n },\n };\n}\n","/**\n * Agent detection and management\n */\n\nimport { execa } from 'execa';\nimport which from 'which';\nimport type { AgentDefinition, AgentStatus, RapidConfig, ExternalAuthConfig } from './types.js';\nimport { getAuthEnvironment } from './external-auth.js';\n\n/**\n * Check if an agent CLI is available\n */\nexport async function checkAgentAvailable(agent: AgentDefinition): Promise<AgentStatus> {\n try {\n const cliPath = await which(agent.cli);\n\n // Try to get version\n let version: string | undefined;\n try {\n const result = await execa(agent.cli, ['--version'], { timeout: 5000 });\n version = result.stdout.trim().split('\\n')[0];\n } catch {\n // Version check failed, but CLI exists\n }\n\n return {\n name: agent.cli,\n available: true,\n cliPath,\n ...(version !== undefined && { version }),\n };\n } catch {\n return {\n name: agent.cli,\n available: false,\n };\n }\n}\n\n/**\n * Check all configured agents\n */\nexport async function checkAllAgents(config: RapidConfig): Promise<AgentStatus[]> {\n const results: AgentStatus[] = [];\n\n for (const [name, agent] of Object.entries(config.agents.available)) {\n const status = await checkAgentAvailable(agent);\n results.push({\n ...status,\n name,\n });\n }\n\n return results;\n}\n\n/**\n * Get the default agent from config\n */\nexport function getDefaultAgent(config: RapidConfig): AgentDefinition | null {\n const defaultName = config.agents.default;\n return config.agents.available[defaultName] || null;\n}\n\n/**\n * Get a specific agent by name\n */\nexport function getAgent(config: RapidConfig, name: string): AgentDefinition | null {\n return config.agents.available[name] || null;\n}\n\n/**\n * Launch an agent CLI\n */\nexport async function launchAgent(\n agent: AgentDefinition,\n options: {\n cwd?: string;\n env?: Record<string, string>;\n stdio?: 'inherit' | 'pipe';\n useExternalAuth?: boolean;\n externalAuthConfig?: ExternalAuthConfig;\n } = {}\n): Promise<void> {\n const args = agent.args ?? [];\n const cwd = options.cwd ?? process.cwd();\n\n // Get external auth environment if enabled\n let authEnv: Record<string, string> = {};\n if (options.useExternalAuth !== false) {\n authEnv = await getAuthEnvironment(options.externalAuthConfig);\n }\n\n await execa(agent.cli, args, {\n cwd,\n env: {\n ...process.env,\n ...authEnv,\n ...options.env, // User-provided env takes precedence\n },\n stdio: options.stdio ?? 'inherit',\n });\n}\n","/**\n * External Authentication Detection\n *\n * Detects and reuses credentials from AI coding tools like:\n * - Claude Code (~/.claude.json)\n * - OpenAI Codex (~/.codex/auth.json)\n * - Gemini CLI (~/.gemini/)\n * - Aider (.env files with API keys)\n */\n\nimport { readFile, access } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { DetectedCredential, ExternalAuthConfig, AuthStatus } from './types.js';\nimport { logger } from './logger.js';\n\n/**\n * Default configuration for external auth detection\n */\nconst DEFAULT_CONFIG: ExternalAuthConfig = {\n enabled: true,\n sources: ['claude-code', 'codex', 'gemini-cli', 'aider', 'env'],\n};\n\n/**\n * Check if a file exists\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Safely read and parse JSON file\n */\nasync function readJsonFile<T>(path: string): Promise<T | null> {\n try {\n const content = await readFile(path, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n// =============================================================================\n// Claude Code Detection\n// =============================================================================\n\ninterface ClaudeCodeConfig {\n oauthAccount?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n accountUuid?: string;\n emailAddress?: string;\n organizationName?: string;\n planType?: string;\n };\n claudeAiOauth?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n };\n lastAccountUuid?: string;\n}\n\n/**\n * Detect Claude Code credentials from ~/.claude.json\n */\nexport async function detectClaudeCodeAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const configPath = join(home, '.claude.json');\n\n if (!(await fileExists(configPath))) {\n return null;\n }\n\n const config = await readJsonFile<ClaudeCodeConfig>(configPath);\n if (!config) {\n return null;\n }\n\n // Check for OAuth session (Claude Pro/Max login)\n const oauth = config.oauthAccount || config.claudeAiOauth;\n if (oauth?.accessToken) {\n const expiresAt = oauth.expiresAt ? new Date(oauth.expiresAt) : undefined;\n\n // Check if token is expired\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Claude Code OAuth token expired');\n return null;\n }\n\n const cred: DetectedCredential = {\n source: 'claude-code',\n provider: 'anthropic',\n authType: 'oauth',\n value: oauth.accessToken,\n configPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (config.oauthAccount?.emailAddress) {\n accountInfo.email = config.oauthAccount.emailAddress;\n }\n if (config.oauthAccount?.organizationName) {\n accountInfo.organization = config.oauthAccount.organizationName;\n }\n if (config.oauthAccount?.planType) {\n accountInfo.plan = config.oauthAccount.planType;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n\n // Check for API key in environment (Claude Code also respects ANTHROPIC_API_KEY)\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (apiKey) {\n return {\n source: 'claude-code',\n provider: 'anthropic',\n authType: 'api-key',\n envVar: 'ANTHROPIC_API_KEY',\n value: apiKey,\n configPath,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// OpenAI Codex Detection\n// =============================================================================\n\ninterface CodexAuthConfig {\n chatgpt?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n email?: string;\n workspaceId?: string;\n };\n api?: {\n apiKey?: string;\n };\n}\n\n/**\n * Detect OpenAI Codex credentials from ~/.codex/auth.json\n */\nexport async function detectCodexAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const configPath = join(home, '.codex', 'auth.json');\n\n if (!(await fileExists(configPath))) {\n return null;\n }\n\n const config = await readJsonFile<CodexAuthConfig>(configPath);\n if (!config) {\n return null;\n }\n\n // Check for ChatGPT OAuth session\n if (config.chatgpt?.accessToken) {\n const expiresAt = config.chatgpt.expiresAt ? new Date(config.chatgpt.expiresAt) : undefined;\n\n // Check if token is expired\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Codex ChatGPT OAuth token expired');\n return null;\n }\n\n const cred: DetectedCredential = {\n source: 'codex',\n provider: 'openai',\n authType: 'oauth',\n value: config.chatgpt.accessToken,\n configPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (config.chatgpt.email) {\n accountInfo.email = config.chatgpt.email;\n }\n if (config.chatgpt.workspaceId) {\n accountInfo.organization = config.chatgpt.workspaceId;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n\n // Check for API key\n if (config.api?.apiKey) {\n return {\n source: 'codex',\n provider: 'openai',\n authType: 'api-key',\n value: config.api.apiKey,\n configPath,\n };\n }\n\n // Check environment variable\n const apiKey = process.env.OPENAI_API_KEY;\n if (apiKey) {\n return {\n source: 'codex',\n provider: 'openai',\n authType: 'api-key',\n envVar: 'OPENAI_API_KEY',\n value: apiKey,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// Gemini CLI Detection\n// =============================================================================\n\ninterface GeminiSettings {\n auth?: {\n oauth?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n email?: string;\n };\n };\n googleCloudProject?: string;\n}\n\n/**\n * Detect Gemini CLI credentials from ~/.gemini/\n */\nexport async function detectGeminiAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const settingsPath = join(home, '.gemini', 'settings.json');\n\n // Check for settings.json with OAuth\n if (await fileExists(settingsPath)) {\n const settings = await readJsonFile<GeminiSettings>(settingsPath);\n if (settings?.auth?.oauth?.accessToken) {\n const oauth = settings.auth.oauth;\n const expiresAt = oauth.expiresAt ? new Date(oauth.expiresAt) : undefined;\n\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Gemini CLI OAuth token expired');\n } else {\n const cred: DetectedCredential = {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'oauth',\n value: oauth.accessToken!,\n configPath: settingsPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (oauth.email) {\n accountInfo.email = oauth.email;\n }\n if (settings.googleCloudProject) {\n accountInfo.organization = settings.googleCloudProject;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n }\n }\n\n // Check for GEMINI_API_KEY environment variable\n const geminiKey = process.env.GEMINI_API_KEY;\n if (geminiKey) {\n return {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GEMINI_API_KEY',\n value: geminiKey,\n };\n }\n\n // Check for GOOGLE_API_KEY environment variable\n const googleKey = process.env.GOOGLE_API_KEY;\n if (googleKey) {\n return {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GOOGLE_API_KEY',\n value: googleKey,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// Aider Detection\n// =============================================================================\n\n/**\n * Detect Aider credentials from environment variables\n * Aider uses standard environment variables, no config file\n */\nexport async function detectAiderAuth(): Promise<DetectedCredential[]> {\n const credentials: DetectedCredential[] = [];\n\n // Anthropic API Key (Aider's preferred for Claude models)\n const anthropicKey = process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n credentials.push({\n source: 'aider',\n provider: 'anthropic',\n authType: 'api-key',\n envVar: 'ANTHROPIC_API_KEY',\n value: anthropicKey,\n });\n }\n\n // OpenAI API Key\n const openaiKey = process.env.OPENAI_API_KEY;\n if (openaiKey) {\n credentials.push({\n source: 'aider',\n provider: 'openai',\n authType: 'api-key',\n envVar: 'OPENAI_API_KEY',\n value: openaiKey,\n });\n }\n\n // Gemini API Key (Aider also supports Gemini)\n const geminiKey = process.env.GEMINI_API_KEY;\n if (geminiKey) {\n credentials.push({\n source: 'aider',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GEMINI_API_KEY',\n value: geminiKey,\n });\n }\n\n return credentials;\n}\n\n// =============================================================================\n// Environment Variable Detection\n// =============================================================================\n\n/**\n * Detect credentials from standard environment variables\n */\nexport async function detectEnvAuth(): Promise<DetectedCredential[]> {\n const credentials: DetectedCredential[] = [];\n\n const envMappings: Array<{\n envVar: string;\n provider: 'anthropic' | 'openai' | 'google';\n }> = [\n { envVar: 'ANTHROPIC_API_KEY', provider: 'anthropic' },\n { envVar: 'OPENAI_API_KEY', provider: 'openai' },\n { envVar: 'GEMINI_API_KEY', provider: 'google' },\n { envVar: 'GOOGLE_API_KEY', provider: 'google' },\n ];\n\n for (const { envVar, provider } of envMappings) {\n const value = process.env[envVar];\n if (value) {\n credentials.push({\n source: 'env',\n provider,\n authType: 'api-key',\n envVar,\n value,\n });\n }\n }\n\n return credentials;\n}\n\n// =============================================================================\n// Main Detection Functions\n// =============================================================================\n\n/**\n * Detect all available credentials from external sources\n */\nexport async function detectAllCredentials(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<DetectedCredential[]> {\n if (!config.enabled) {\n return [];\n }\n\n const sources = config.sources || DEFAULT_CONFIG.sources!;\n const credentials: DetectedCredential[] = [];\n const seenValues = new Set<string>();\n\n for (const source of sources) {\n try {\n let detected: DetectedCredential | DetectedCredential[] | null = null;\n\n switch (source) {\n case 'claude-code':\n detected = await detectClaudeCodeAuth();\n break;\n case 'codex':\n detected = await detectCodexAuth();\n break;\n case 'gemini-cli':\n detected = await detectGeminiAuth();\n break;\n case 'aider':\n detected = await detectAiderAuth();\n break;\n case 'env':\n detected = await detectEnvAuth();\n break;\n }\n\n if (detected) {\n const items = Array.isArray(detected) ? detected : [detected];\n for (const item of items) {\n // Deduplicate by value to avoid listing the same API key multiple times\n const key = item.value || item.envVar || '';\n if (key && !seenValues.has(key)) {\n seenValues.add(key);\n credentials.push(item);\n }\n }\n }\n } catch (error) {\n logger.debug(`Error detecting ${source} credentials:`, error);\n }\n }\n\n return credentials;\n}\n\n/**\n * Get authentication status summary\n */\nexport async function getAuthStatus(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<AuthStatus> {\n const credentials = await detectAllCredentials(config);\n const warnings: string[] = [];\n\n // Check for expired tokens\n for (const cred of credentials) {\n if (cred.expiresAt && cred.expiresAt < new Date()) {\n warnings.push(`${cred.source} OAuth token has expired. Please re-authenticate.`);\n }\n }\n\n // Find preferred source\n let preferredSource: DetectedCredential | undefined;\n if (config.preferSource) {\n preferredSource = credentials.find((c) => c.source === config.preferSource);\n }\n\n // If no preferred source specified, prioritize OAuth over API keys\n if (!preferredSource && credentials.length > 0) {\n preferredSource = credentials.find((c) => c.authType === 'oauth') || credentials[0];\n }\n\n const result: AuthStatus = {\n authenticated: credentials.length > 0,\n sources: credentials,\n };\n\n if (preferredSource) {\n result.preferredSource = preferredSource;\n }\n\n if (warnings.length > 0) {\n result.warnings = warnings;\n }\n\n return result;\n}\n\n/**\n * Get credentials for a specific provider\n */\nexport async function getCredentialsForProvider(\n provider: 'anthropic' | 'openai' | 'google',\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<DetectedCredential | null> {\n const credentials = await detectAllCredentials(config);\n const providerCreds = credentials.filter((c) => c.provider === provider);\n\n if (providerCreds.length === 0) {\n return null;\n }\n\n // Prefer OAuth over API keys\n const found = providerCreds.find((c) => c.authType === 'oauth');\n return found || providerCreds[0] || null;\n}\n\n/**\n * Get environment variables to inject based on detected credentials\n */\nexport async function getAuthEnvironment(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<Record<string, string>> {\n const credentials = await detectAllCredentials(config);\n const env: Record<string, string> = {};\n\n // Group by provider and prefer OAuth tokens\n const byProvider = new Map<string, DetectedCredential>();\n\n for (const cred of credentials) {\n const existing = byProvider.get(cred.provider);\n // Prefer OAuth over API keys\n if (!existing || (cred.authType === 'oauth' && existing.authType !== 'oauth')) {\n byProvider.set(cred.provider, cred);\n }\n }\n\n // Map to environment variables\n for (const [provider, cred] of byProvider) {\n if (!cred.value) continue;\n\n switch (provider) {\n case 'anthropic':\n // For OAuth tokens, we use ANTHROPIC_AUTH_TOKEN\n // For API keys, we use ANTHROPIC_API_KEY\n if (cred.authType === 'oauth') {\n env['ANTHROPIC_AUTH_TOKEN'] = cred.value;\n } else {\n env['ANTHROPIC_API_KEY'] = cred.value;\n }\n break;\n\n case 'openai':\n if (cred.authType === 'oauth') {\n // OpenAI Codex uses a different auth header for OAuth\n env['OPENAI_AUTH_TOKEN'] = cred.value;\n } else {\n env['OPENAI_API_KEY'] = cred.value;\n }\n break;\n\n case 'google':\n if (cred.authType === 'oauth') {\n env['GOOGLE_AUTH_TOKEN'] = cred.value;\n } else {\n // Prefer GEMINI_API_KEY, fallback to GOOGLE_API_KEY\n if (cred.envVar === 'GOOGLE_API_KEY') {\n env['GOOGLE_API_KEY'] = cred.value;\n } else {\n env['GEMINI_API_KEY'] = cred.value;\n }\n }\n break;\n }\n }\n\n return env;\n}\n\n/**\n * Format auth status for display\n */\nexport function formatAuthStatus(status: AuthStatus): string {\n const lines: string[] = [];\n\n if (!status.authenticated) {\n lines.push('No authentication detected');\n lines.push('');\n lines.push('To authenticate, either:');\n lines.push(' - Log in with Claude Code: claude');\n lines.push(' - Log in with Codex: codex');\n lines.push(' - Log in with Gemini CLI: gemini');\n lines.push(' - Set environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)');\n return lines.join('\\n');\n }\n\n lines.push('Detected authentication sources:');\n lines.push('');\n\n for (const cred of status.sources) {\n const isPrimary = cred === status.preferredSource;\n const prefix = isPrimary ? '* ' : ' ';\n const authType = cred.authType === 'oauth' ? 'OAuth' : 'API Key';\n\n let line = `${prefix}${cred.source} (${cred.provider}, ${authType})`;\n\n if (cred.accountInfo?.email) {\n line += ` - ${cred.accountInfo.email}`;\n }\n if (cred.accountInfo?.plan) {\n line += ` [${cred.accountInfo.plan}]`;\n }\n if (cred.expiresAt) {\n const expiresIn = Math.round((cred.expiresAt.getTime() - Date.now()) / 1000 / 60);\n if (expiresIn > 0) {\n line += ` (expires in ${expiresIn}m)`;\n } else {\n line += ' (EXPIRED)';\n }\n }\n\n lines.push(line);\n }\n\n if (status.warnings && status.warnings.length > 0) {\n lines.push('');\n lines.push('Warnings:');\n for (const warning of status.warnings) {\n lines.push(` ! ${warning}`);\n }\n }\n\n return lines.join('\\n');\n}\n","/**\n * Logging utilities\n */\n\nimport chalk from 'chalk';\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet currentLevel: LogLevel = 'info';\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nexport function getLogLevel(): LogLevel {\n return currentLevel;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];\n}\n\nexport const logger = {\n debug(message: string, ...args: unknown[]): void {\n if (shouldLog('debug')) {\n console.log(chalk.gray(`[debug] ${message}`), ...args);\n }\n },\n\n info(message: string, ...args: unknown[]): void {\n if (shouldLog('info')) {\n console.log(chalk.blue('ℹ'), message, ...args);\n }\n },\n\n success(message: string, ...args: unknown[]): void {\n if (shouldLog('info')) {\n console.log(chalk.green('✓'), message, ...args);\n }\n },\n\n warn(message: string, ...args: unknown[]): void {\n if (shouldLog('warn')) {\n console.log(chalk.yellow('⚠'), message, ...args);\n }\n },\n\n error(message: string, ...args: unknown[]): void {\n if (shouldLog('error')) {\n console.error(chalk.red('✗'), message, ...args);\n }\n },\n\n // Styled output helpers\n brand(text: string): string {\n return chalk.hex('#818cf8')(text);\n },\n\n dim(text: string): string {\n return chalk.dim(text);\n },\n\n bold(text: string): string {\n return chalk.bold(text);\n },\n\n // Print a header\n header(text: string): void {\n console.log();\n console.log(chalk.bold(text));\n console.log(chalk.dim('─'.repeat(text.length)));\n },\n\n // Print a blank line\n blank(): void {\n console.log();\n },\n};\n","/**\n * Container management utilities\n * Uses devcontainer CLI for container lifecycle\n */\n\nimport { execa, type ExecaError } from 'execa';\nimport which from 'which';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RapidConfig } from './types.js';\n\nexport interface ContainerStatus {\n exists: boolean;\n running: boolean;\n containerId?: string;\n containerName?: string;\n}\n\nexport interface DevcontainerConfig {\n name?: string;\n image?: string;\n dockerFile?: string;\n build?: {\n dockerfile?: string;\n context?: string;\n };\n [key: string]: unknown;\n}\n\n/**\n * Check if devcontainer CLI is available\n */\nexport async function hasDevcontainerCli(): Promise<boolean> {\n try {\n await which('devcontainer');\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if Docker is available\n */\nexport async function hasDocker(): Promise<boolean> {\n try {\n await execa('docker', ['info'], { timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the devcontainer.json path\n */\nexport function getDevcontainerPath(rootDir: string, config?: RapidConfig): string {\n const customPath = config?.container?.devcontainer;\n if (customPath) {\n return join(rootDir, customPath);\n }\n return join(rootDir, '.devcontainer', 'devcontainer.json');\n}\n\n/**\n * Load devcontainer.json\n */\nexport async function loadDevcontainerConfig(\n rootDir: string,\n config?: RapidConfig\n): Promise<DevcontainerConfig | null> {\n try {\n const configPath = getDevcontainerPath(rootDir, config);\n const content = await readFile(configPath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Get container name for a project\n */\nexport function getContainerName(rootDir: string, devcontainerConfig?: DevcontainerConfig): string {\n // Use devcontainer name if available, otherwise derive from directory\n const dirName = rootDir.split('/').pop() || 'rapid';\n const name = devcontainerConfig?.name || dirName;\n // Sanitize for Docker container name\n return `rapid-${name}`.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n}\n\n/**\n * Check container status using devcontainer labels\n */\nexport async function getContainerStatus(\n rootDir: string,\n _config?: RapidConfig\n): Promise<ContainerStatus> {\n try {\n // Use devcontainer label to find the container (this is how devcontainer CLI tracks containers)\n const result = await execa('docker', [\n 'ps',\n '-a',\n '--filter',\n `label=devcontainer.local_folder=${rootDir}`,\n '--format',\n '{{.ID}}\\t{{.State}}\\t{{.Names}}',\n ]);\n\n const lines = result.stdout.trim().split('\\n').filter(Boolean);\n if (lines.length === 0) {\n return { exists: false, running: false };\n }\n\n const parts = lines[0]?.split('\\t');\n const containerId = parts?.[0];\n const state = parts?.[1];\n const containerName = parts?.[2];\n\n if (!containerId || !containerName) {\n return { exists: false, running: false };\n }\n\n return {\n exists: true,\n running: state === 'running',\n containerId,\n containerName,\n };\n } catch {\n return { exists: false, running: false };\n }\n}\n\n/**\n * Start the dev container using devcontainer CLI\n */\nexport async function startContainer(\n rootDir: string,\n _config?: RapidConfig,\n options: { rebuild?: boolean; quiet?: boolean } = {}\n): Promise<{ success: boolean; containerId?: string; error?: string }> {\n const hasDevCli = await hasDevcontainerCli();\n\n if (!hasDevCli) {\n return {\n success: false,\n error: 'devcontainer CLI not found. Install with: npm install -g @devcontainers/cli',\n };\n }\n\n const hasDockerRunning = await hasDocker();\n if (!hasDockerRunning) {\n return {\n success: false,\n error: 'Docker is not running. Please start Docker Desktop.',\n };\n }\n\n try {\n const args = ['up', '--workspace-folder', rootDir];\n\n if (options.rebuild) {\n args.push('--remove-existing-container');\n }\n\n const result = await execa('devcontainer', args, {\n stdio: options.quiet ? 'pipe' : 'inherit',\n cwd: rootDir,\n });\n\n // Parse the container ID from output\n // devcontainer up outputs JSON with containerId\n if (options.quiet && result.stdout) {\n try {\n const output = JSON.parse(result.stdout);\n return { success: true, containerId: output.containerId };\n } catch {\n return { success: true };\n }\n }\n\n return { success: true };\n } catch (error) {\n const execError = error as ExecaError;\n const stderr = typeof execError.stderr === 'string' ? execError.stderr : undefined;\n return {\n success: false,\n error: stderr || execError.message,\n };\n }\n}\n\n/**\n * Stop the dev container\n */\nexport async function stopContainer(\n rootDir: string,\n config?: RapidConfig,\n options: { remove?: boolean } = {}\n): Promise<{ success: boolean; error?: string }> {\n const status = await getContainerStatus(rootDir, config);\n\n if (!status.exists) {\n return { success: true }; // Nothing to stop\n }\n\n try {\n if (status.running) {\n await execa('docker', ['stop', status.containerId!]);\n }\n\n if (options.remove) {\n await execa('docker', ['rm', status.containerId!]);\n }\n\n return { success: true };\n } catch (error) {\n const execError = error as ExecaError;\n const stderr = typeof execError.stderr === 'string' ? execError.stderr : undefined;\n return {\n success: false,\n error: stderr || execError.message,\n };\n }\n}\n\n/**\n * Execute a command inside the dev container\n */\nexport async function execInContainer(\n rootDir: string,\n command: string[],\n _config?: RapidConfig,\n options: { interactive?: boolean; tty?: boolean; env?: Record<string, string> } = {}\n): Promise<void> {\n const hasDevCli = await hasDevcontainerCli();\n\n if (!hasDevCli) {\n throw new Error('devcontainer CLI not found. Install with: npm install -g @devcontainers/cli');\n }\n\n const args = ['exec', '--workspace-folder', rootDir];\n\n // Add environment variables\n if (options.env) {\n for (const [key, value] of Object.entries(options.env)) {\n args.push('--remote-env', `${key}=${value}`);\n }\n }\n\n // Add the command\n args.push(...command);\n\n await execa('devcontainer', args, {\n stdio: 'inherit',\n cwd: rootDir,\n });\n}\n","/**\n * Secrets management for RAPID\n * Supports 1Password, HashiCorp Vault, and environment variables\n */\n\nimport { spawn } from 'node:child_process';\nimport { readFile, writeFile, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { SecretsConfig } from './types.js';\nimport { logger } from './logger.js';\n\nexport interface SecretStatus {\n name: string;\n reference: string;\n provider: 'env' | '1password' | 'vault';\n available: boolean;\n error?: string;\n}\n\nexport interface SecretsStatus {\n provider: 'env' | '1password' | 'vault';\n authenticated: boolean;\n authMethod?: 'service-account' | 'user' | 'token';\n secrets: SecretStatus[];\n allAvailable: boolean;\n}\n\nexport interface OpAuthStatus {\n authenticated: boolean;\n method: 'service-account' | 'user' | 'none';\n accountInfo?: string;\n}\n\n/**\n * Execute a command and return stdout\n */\nasync function execCommand(\n command: string,\n args: string[],\n options: { timeout?: number } = {}\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: options.timeout ?? 30000,\n });\n\n let stdout = '';\n let stderr = '';\n\n proc.stdout?.on('data', (data) => {\n stdout += data.toString();\n });\n\n proc.stderr?.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.on('close', (code) => {\n resolve({ stdout: stdout.trim(), stderr: stderr.trim(), exitCode: code ?? 1 });\n });\n\n proc.on('error', (err) => {\n resolve({ stdout: '', stderr: err.message, exitCode: 1 });\n });\n });\n}\n\n/**\n * Check if 1Password CLI is installed\n */\nexport async function hasOpCli(): Promise<boolean> {\n const result = await execCommand('op', ['--version']);\n return result.exitCode === 0;\n}\n\n/**\n * Check if OP_SERVICE_ACCOUNT_TOKEN is set\n */\nexport function hasOpServiceAccountToken(): boolean {\n return !!process.env.OP_SERVICE_ACCOUNT_TOKEN;\n}\n\n/**\n * Check if 1Password CLI is authenticated (via service account or user)\n */\nexport async function isOpAuthenticated(): Promise<boolean> {\n // Service account token takes precedence\n if (hasOpServiceAccountToken()) {\n // Verify the token works by trying to list vaults\n const result = await execCommand('op', ['vault', 'list', '--format=json']);\n return result.exitCode === 0;\n }\n\n // Fall back to user authentication\n const result = await execCommand('op', ['account', 'list']);\n return result.exitCode === 0 && result.stdout.length > 0;\n}\n\n/**\n * Get detailed 1Password authentication status\n */\nexport async function getOpAuthStatus(): Promise<OpAuthStatus> {\n // Check for service account token first\n if (hasOpServiceAccountToken()) {\n const result = await execCommand('op', ['vault', 'list', '--format=json']);\n if (result.exitCode === 0) {\n return {\n authenticated: true,\n method: 'service-account',\n accountInfo: 'Service Account',\n };\n }\n return {\n authenticated: false,\n method: 'none',\n accountInfo: 'Invalid service account token',\n };\n }\n\n // Check for user authentication\n const result = await execCommand('op', ['account', 'list', '--format=json']);\n if (result.exitCode === 0 && result.stdout.length > 0) {\n try {\n const accounts = JSON.parse(result.stdout);\n if (accounts.length > 0) {\n return {\n authenticated: true,\n method: 'user',\n accountInfo: accounts[0].email || accounts[0].url,\n };\n }\n } catch {\n // Parse error, but command succeeded\n return {\n authenticated: true,\n method: 'user',\n };\n }\n }\n\n return {\n authenticated: false,\n method: 'none',\n };\n}\n\n/**\n * Check if HashiCorp Vault CLI is installed\n */\nexport async function hasVaultCli(): Promise<boolean> {\n const result = await execCommand('vault', ['--version']);\n return result.exitCode === 0;\n}\n\n/**\n * Check if HashiCorp Vault is authenticated\n */\nexport async function isVaultAuthenticated(): Promise<boolean> {\n const result = await execCommand('vault', ['token', 'lookup']);\n return result.exitCode === 0;\n}\n\n/**\n * Read a secret from 1Password\n * @param reference - 1Password reference (e.g., \"op://vault/item/field\")\n */\nexport async function readOpSecret(reference: string): Promise<string | null> {\n const result = await execCommand('op', ['read', reference]);\n if (result.exitCode !== 0) {\n return null;\n }\n return result.stdout;\n}\n\n/**\n * Read a secret from HashiCorp Vault\n * @param path - Vault path (e.g., \"secret/data/myproject\")\n * @param field - Field name within the secret\n */\nexport async function readVaultSecret(path: string, field: string): Promise<string | null> {\n const result = await execCommand('vault', ['kv', 'get', '-field', field, path]);\n if (result.exitCode !== 0) {\n return null;\n }\n return result.stdout;\n}\n\n/**\n * Verify a single secret is accessible\n */\nexport async function verifySecret(\n name: string,\n reference: string,\n provider: 'env' | '1password' | 'vault',\n config?: SecretsConfig\n): Promise<SecretStatus> {\n const status: SecretStatus = {\n name,\n reference,\n provider,\n available: false,\n };\n\n try {\n switch (provider) {\n case 'env': {\n const value = process.env[name];\n status.available = !!value && value.length > 0;\n if (!status.available) {\n status.error = 'Environment variable not set';\n }\n break;\n }\n\n case '1password': {\n // Reference should be in format op://vault/item/field\n const value = await readOpSecret(reference);\n status.available = value !== null;\n if (!status.available) {\n status.error = 'Secret not found in 1Password';\n }\n break;\n }\n\n case 'vault': {\n // Parse path and field from reference\n const field = reference.split('/').pop() || 'value';\n const vaultPath = reference.includes('/')\n ? reference.substring(0, reference.lastIndexOf('/'))\n : config?.vault || 'secret/data/default';\n\n const value = await readVaultSecret(vaultPath, field);\n status.available = value !== null;\n if (!status.available) {\n status.error = 'Secret not found in Vault';\n }\n break;\n }\n }\n } catch (error) {\n status.error = error instanceof Error ? error.message : String(error);\n status.available = false;\n }\n\n return status;\n}\n\n/**\n * Verify all secrets in configuration\n */\nexport async function verifySecrets(config: SecretsConfig): Promise<SecretsStatus> {\n const provider = config.provider || 'env';\n let authenticated = true;\n\n // Check authentication status for provider\n switch (provider) {\n case '1password':\n authenticated = await isOpAuthenticated();\n break;\n case 'vault':\n authenticated = await isVaultAuthenticated();\n break;\n case 'env':\n authenticated = true;\n break;\n }\n\n const secrets: SecretStatus[] = [];\n\n if (config.items) {\n for (const [name, reference] of Object.entries(config.items)) {\n const status = await verifySecret(name, reference, provider, config);\n secrets.push(status);\n }\n }\n\n const allAvailable = secrets.length === 0 || secrets.every((s) => s.available);\n\n return {\n provider,\n authenticated,\n secrets,\n allAvailable,\n };\n}\n\n/**\n * Load all secrets into environment\n */\nexport async function loadSecrets(config: SecretsConfig): Promise<Record<string, string>> {\n const provider = config.provider || 'env';\n const secrets: Record<string, string> = {};\n\n if (!config.items) {\n return secrets;\n }\n\n for (const [name, reference] of Object.entries(config.items)) {\n try {\n let value: string | null = null;\n\n switch (provider) {\n case 'env':\n value = process.env[name] || null;\n break;\n\n case '1password':\n value = await readOpSecret(reference);\n break;\n\n case 'vault': {\n const field = reference.split('/').pop() || 'value';\n const path = reference.substring(0, reference.lastIndexOf('/')) || config.vault || '';\n value = await readVaultSecret(path, field);\n break;\n }\n }\n\n if (value) {\n secrets[name] = value;\n }\n } catch (error) {\n logger.debug(`Failed to load secret ${name}: ${error}`);\n }\n }\n\n return secrets;\n}\n\n/**\n * Generate .envrc file from secrets configuration\n */\nexport function generateEnvrc(config: SecretsConfig): string {\n const provider = config.provider || 'env';\n const lines: string[] = [\n '# .envrc - RAPID project secrets',\n '# This file is safe to commit - it contains NO secrets, only references',\n '#',\n `# Provider: ${provider}`,\n `# Generated by: rapid secrets generate`,\n '',\n ];\n\n if (!config.items || Object.keys(config.items).length === 0) {\n lines.push('# No secrets configured in rapid.json');\n return lines.join('\\n');\n }\n\n switch (provider) {\n case '1password':\n lines.push('# Secrets loaded from 1Password');\n lines.push('# Requires: 1Password CLI (op) installed and authenticated');\n lines.push('');\n for (const [name, reference] of Object.entries(config.items)) {\n lines.push(`export ${name}=$(op read \"${reference}\")`);\n }\n break;\n\n case 'vault':\n lines.push('# Secrets loaded from HashiCorp Vault');\n lines.push('# Requires: Vault CLI installed and authenticated');\n lines.push('');\n if (config.address) {\n lines.push(`export VAULT_ADDR=\"${config.address}\"`);\n lines.push('');\n }\n for (const [name, reference] of Object.entries(config.items)) {\n const path = config.vault || 'secret/data/default';\n lines.push(`export ${name}=$(vault kv get -field=${reference} ${path})`);\n }\n break;\n\n case 'env':\n lines.push('# WARNING: env provider expects secrets to be set manually');\n lines.push('# Consider using 1password or vault for better security');\n lines.push('');\n lines.push('# Uncomment and set values (DO NOT commit actual values!)');\n for (const name of Object.keys(config.items)) {\n lines.push(`# export ${name}=\"your-value-here\"`);\n }\n break;\n }\n\n // Add .env.local loading if configured\n if (config.envrc?.includeLocal !== false) {\n lines.push('');\n lines.push('# Load local overrides if present');\n lines.push('[[ -f .env.local ]] && source_env .env.local');\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Write .envrc file to project directory\n */\nexport async function writeEnvrc(rootDir: string, config: SecretsConfig): Promise<string> {\n const envrcPath = config.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n const content = generateEnvrc(config);\n\n await writeFile(fullPath, content);\n return fullPath;\n}\n\n/**\n * Check if .envrc exists in project\n */\nexport async function hasEnvrc(rootDir: string, config?: SecretsConfig): Promise<boolean> {\n const envrcPath = config?.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n\n try {\n await access(fullPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read existing .envrc content\n */\nexport async function readEnvrc(rootDir: string, config?: SecretsConfig): Promise<string | null> {\n const envrcPath = config?.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n\n try {\n const content = await readFile(fullPath, 'utf-8');\n return content;\n } catch {\n return null;\n }\n}\n\n/**\n * Get a summary of provider requirements\n */\nexport function getProviderInfo(provider: 'env' | '1password' | 'vault'): {\n name: string;\n cliRequired: string | null;\n authCommand: string | null;\n installUrl: string | null;\n} {\n switch (provider) {\n case '1password':\n return {\n name: '1Password',\n cliRequired: 'op',\n authCommand: 'eval $(op signin)',\n installUrl: 'https://developer.1password.com/docs/cli/get-started/',\n };\n case 'vault':\n return {\n name: 'HashiCorp Vault',\n cliRequired: 'vault',\n authCommand: 'vault login',\n installUrl: 'https://developer.hashicorp.com/vault/docs/install',\n };\n case 'env':\n return {\n name: 'Environment Variables',\n cliRequired: null,\n authCommand: null,\n installUrl: null,\n };\n }\n}\n"],"mappings":"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","names":["readFile","readFile","execa","which","readFile","join","readFile","access","join","resolve","result","join","access","readFile"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/agents.ts","../src/external-auth.ts","../src/logger.ts","../src/container.ts","../src/secrets.ts","../src/mcp.ts","../src/mcp-templates.ts"],"sourcesContent":["/**\n * Configuration loading and validation\n */\n\nimport { cosmiconfig } from 'cosmiconfig';\nimport { readFile } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport type { RapidConfig } from './types.js';\n\nconst CONFIG_NAME = 'rapid';\nconst CONFIG_FILES = ['rapid.json', 'rapid.config.json', '.rapidrc', '.rapidrc.json'];\n\nexport interface LoadedConfig {\n config: RapidConfig;\n filepath: string;\n rootDir: string;\n}\n\n/**\n * Load RAPID configuration from the current directory or ancestors\n */\nexport async function loadConfig(cwd?: string): Promise<LoadedConfig | null> {\n const explorer = cosmiconfig(CONFIG_NAME, {\n searchPlaces: CONFIG_FILES,\n loaders: {\n '.json': async (filepath) => {\n const content = await readFile(filepath, 'utf-8');\n return JSON.parse(content);\n },\n },\n });\n\n const result = await explorer.search(cwd);\n\n if (!result || result.isEmpty) {\n return null;\n }\n\n return {\n config: result.config as RapidConfig,\n filepath: result.filepath,\n rootDir: dirname(result.filepath),\n };\n}\n\n/**\n * Load configuration from a specific file\n */\nexport async function loadConfigFromFile(filepath: string): Promise<LoadedConfig> {\n const content = await readFile(filepath, 'utf-8');\n const config = JSON.parse(content) as RapidConfig;\n\n return {\n config,\n filepath: resolve(filepath),\n rootDir: dirname(resolve(filepath)),\n };\n}\n\n/**\n * Get default configuration\n */\nexport function getDefaultConfig(): RapidConfig {\n return {\n version: '1.0',\n agents: {\n default: 'claude',\n available: {\n claude: {\n cli: 'claude',\n instructionFile: 'CLAUDE.md',\n envVars: ['ANTHROPIC_API_KEY'],\n },\n opencode: {\n cli: 'opencode',\n instructionFile: 'AGENTS.md',\n envVars: ['ANTHROPIC_API_KEY'],\n },\n aider: {\n cli: 'aider',\n instructionFile: 'AGENTS.md',\n envVars: ['ANTHROPIC_API_KEY'],\n args: ['--model', 'claude-3-5-sonnet-20241022'],\n },\n },\n },\n secrets: {\n provider: 'env',\n },\n context: {\n files: ['README.md'],\n dirs: ['docs/'],\n generateAgentFiles: true,\n },\n };\n}\n\n/**\n * Merge user config with defaults\n */\nexport function mergeWithDefaults(config: Partial<RapidConfig>): RapidConfig {\n const defaults = getDefaultConfig();\n\n return {\n ...defaults,\n ...config,\n agents: {\n ...defaults.agents,\n ...config.agents,\n available: {\n ...defaults.agents.available,\n ...config.agents?.available,\n },\n },\n secrets: {\n ...defaults.secrets,\n ...config.secrets,\n },\n context: {\n ...defaults.context,\n ...config.context,\n },\n };\n}\n","/**\n * Agent detection and management\n */\n\nimport { execa } from 'execa';\nimport which from 'which';\nimport type { AgentDefinition, AgentStatus, RapidConfig, ExternalAuthConfig } from './types.js';\nimport { getAuthEnvironment } from './external-auth.js';\n\n/**\n * Check if an agent CLI is available\n */\nexport async function checkAgentAvailable(agent: AgentDefinition): Promise<AgentStatus> {\n try {\n const cliPath = await which(agent.cli);\n\n // Try to get version\n let version: string | undefined;\n try {\n const result = await execa(agent.cli, ['--version'], { timeout: 5000 });\n version = result.stdout.trim().split('\\n')[0];\n } catch {\n // Version check failed, but CLI exists\n }\n\n return {\n name: agent.cli,\n available: true,\n cliPath,\n ...(version !== undefined && { version }),\n };\n } catch {\n return {\n name: agent.cli,\n available: false,\n };\n }\n}\n\n/**\n * Check all configured agents\n */\nexport async function checkAllAgents(config: RapidConfig): Promise<AgentStatus[]> {\n const results: AgentStatus[] = [];\n\n for (const [name, agent] of Object.entries(config.agents.available)) {\n const status = await checkAgentAvailable(agent);\n results.push({\n ...status,\n name,\n });\n }\n\n return results;\n}\n\n/**\n * Get the default agent from config\n */\nexport function getDefaultAgent(config: RapidConfig): AgentDefinition | null {\n const defaultName = config.agents.default;\n return config.agents.available[defaultName] || null;\n}\n\n/**\n * Get a specific agent by name\n */\nexport function getAgent(config: RapidConfig, name: string): AgentDefinition | null {\n return config.agents.available[name] || null;\n}\n\n/**\n * Launch an agent CLI\n */\nexport async function launchAgent(\n agent: AgentDefinition,\n options: {\n cwd?: string;\n env?: Record<string, string>;\n stdio?: 'inherit' | 'pipe';\n useExternalAuth?: boolean;\n externalAuthConfig?: ExternalAuthConfig;\n } = {}\n): Promise<void> {\n const args = agent.args ?? [];\n const cwd = options.cwd ?? process.cwd();\n\n // Get external auth environment if enabled\n let authEnv: Record<string, string> = {};\n if (options.useExternalAuth !== false) {\n authEnv = await getAuthEnvironment(options.externalAuthConfig);\n }\n\n await execa(agent.cli, args, {\n cwd,\n env: {\n ...process.env,\n ...authEnv,\n ...options.env, // User-provided env takes precedence\n },\n stdio: options.stdio ?? 'inherit',\n });\n}\n","/**\n * External Authentication Detection\n *\n * Detects and reuses credentials from AI coding tools like:\n * - Claude Code (~/.claude.json)\n * - OpenAI Codex (~/.codex/auth.json)\n * - Gemini CLI (~/.gemini/)\n * - Aider (.env files with API keys)\n */\n\nimport { readFile, access } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { DetectedCredential, ExternalAuthConfig, AuthStatus } from './types.js';\nimport { logger } from './logger.js';\n\n/**\n * Default configuration for external auth detection\n */\nconst DEFAULT_CONFIG: ExternalAuthConfig = {\n enabled: true,\n sources: ['claude-code', 'codex', 'gemini-cli', 'aider', 'env'],\n};\n\n/**\n * Check if a file exists\n */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Safely read and parse JSON file\n */\nasync function readJsonFile<T>(path: string): Promise<T | null> {\n try {\n const content = await readFile(path, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n// =============================================================================\n// Claude Code Detection\n// =============================================================================\n\ninterface ClaudeCodeConfig {\n oauthAccount?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n accountUuid?: string;\n emailAddress?: string;\n organizationName?: string;\n planType?: string;\n };\n claudeAiOauth?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n };\n lastAccountUuid?: string;\n}\n\n/**\n * Detect Claude Code credentials from ~/.claude.json\n */\nexport async function detectClaudeCodeAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const configPath = join(home, '.claude.json');\n\n if (!(await fileExists(configPath))) {\n return null;\n }\n\n const config = await readJsonFile<ClaudeCodeConfig>(configPath);\n if (!config) {\n return null;\n }\n\n // Check for OAuth session (Claude Pro/Max login)\n const oauth = config.oauthAccount || config.claudeAiOauth;\n if (oauth?.accessToken) {\n const expiresAt = oauth.expiresAt ? new Date(oauth.expiresAt) : undefined;\n\n // Check if token is expired\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Claude Code OAuth token expired');\n return null;\n }\n\n const cred: DetectedCredential = {\n source: 'claude-code',\n provider: 'anthropic',\n authType: 'oauth',\n value: oauth.accessToken,\n configPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (config.oauthAccount?.emailAddress) {\n accountInfo.email = config.oauthAccount.emailAddress;\n }\n if (config.oauthAccount?.organizationName) {\n accountInfo.organization = config.oauthAccount.organizationName;\n }\n if (config.oauthAccount?.planType) {\n accountInfo.plan = config.oauthAccount.planType;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n\n // Check for API key in environment (Claude Code also respects ANTHROPIC_API_KEY)\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (apiKey) {\n return {\n source: 'claude-code',\n provider: 'anthropic',\n authType: 'api-key',\n envVar: 'ANTHROPIC_API_KEY',\n value: apiKey,\n configPath,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// OpenAI Codex Detection\n// =============================================================================\n\ninterface CodexAuthConfig {\n chatgpt?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n email?: string;\n workspaceId?: string;\n };\n api?: {\n apiKey?: string;\n };\n}\n\n/**\n * Detect OpenAI Codex credentials from ~/.codex/auth.json\n */\nexport async function detectCodexAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const configPath = join(home, '.codex', 'auth.json');\n\n if (!(await fileExists(configPath))) {\n return null;\n }\n\n const config = await readJsonFile<CodexAuthConfig>(configPath);\n if (!config) {\n return null;\n }\n\n // Check for ChatGPT OAuth session\n if (config.chatgpt?.accessToken) {\n const expiresAt = config.chatgpt.expiresAt ? new Date(config.chatgpt.expiresAt) : undefined;\n\n // Check if token is expired\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Codex ChatGPT OAuth token expired');\n return null;\n }\n\n const cred: DetectedCredential = {\n source: 'codex',\n provider: 'openai',\n authType: 'oauth',\n value: config.chatgpt.accessToken,\n configPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (config.chatgpt.email) {\n accountInfo.email = config.chatgpt.email;\n }\n if (config.chatgpt.workspaceId) {\n accountInfo.organization = config.chatgpt.workspaceId;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n\n // Check for API key\n if (config.api?.apiKey) {\n return {\n source: 'codex',\n provider: 'openai',\n authType: 'api-key',\n value: config.api.apiKey,\n configPath,\n };\n }\n\n // Check environment variable\n const apiKey = process.env.OPENAI_API_KEY;\n if (apiKey) {\n return {\n source: 'codex',\n provider: 'openai',\n authType: 'api-key',\n envVar: 'OPENAI_API_KEY',\n value: apiKey,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// Gemini CLI Detection\n// =============================================================================\n\ninterface GeminiSettings {\n auth?: {\n oauth?: {\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string;\n email?: string;\n };\n };\n googleCloudProject?: string;\n}\n\n/**\n * Detect Gemini CLI credentials from ~/.gemini/\n */\nexport async function detectGeminiAuth(): Promise<DetectedCredential | null> {\n const home = homedir();\n const settingsPath = join(home, '.gemini', 'settings.json');\n\n // Check for settings.json with OAuth\n if (await fileExists(settingsPath)) {\n const settings = await readJsonFile<GeminiSettings>(settingsPath);\n if (settings?.auth?.oauth?.accessToken) {\n const oauth = settings.auth.oauth;\n const expiresAt = oauth.expiresAt ? new Date(oauth.expiresAt) : undefined;\n\n if (expiresAt && expiresAt < new Date()) {\n logger.debug('Gemini CLI OAuth token expired');\n } else {\n const cred: DetectedCredential = {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'oauth',\n value: oauth.accessToken!,\n configPath: settingsPath,\n };\n\n if (expiresAt) {\n cred.expiresAt = expiresAt;\n }\n\n const accountInfo: {\n email?: string;\n organization?: string;\n plan?: string;\n } = {};\n\n if (oauth.email) {\n accountInfo.email = oauth.email;\n }\n if (settings.googleCloudProject) {\n accountInfo.organization = settings.googleCloudProject;\n }\n\n if (Object.keys(accountInfo).length > 0) {\n cred.accountInfo = accountInfo;\n }\n\n return cred;\n }\n }\n }\n\n // Check for GEMINI_API_KEY environment variable\n const geminiKey = process.env.GEMINI_API_KEY;\n if (geminiKey) {\n return {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GEMINI_API_KEY',\n value: geminiKey,\n };\n }\n\n // Check for GOOGLE_API_KEY environment variable\n const googleKey = process.env.GOOGLE_API_KEY;\n if (googleKey) {\n return {\n source: 'gemini-cli',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GOOGLE_API_KEY',\n value: googleKey,\n };\n }\n\n return null;\n}\n\n// =============================================================================\n// Aider Detection\n// =============================================================================\n\n/**\n * Detect Aider credentials from environment variables\n * Aider uses standard environment variables, no config file\n */\nexport async function detectAiderAuth(): Promise<DetectedCredential[]> {\n const credentials: DetectedCredential[] = [];\n\n // Anthropic API Key (Aider's preferred for Claude models)\n const anthropicKey = process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n credentials.push({\n source: 'aider',\n provider: 'anthropic',\n authType: 'api-key',\n envVar: 'ANTHROPIC_API_KEY',\n value: anthropicKey,\n });\n }\n\n // OpenAI API Key\n const openaiKey = process.env.OPENAI_API_KEY;\n if (openaiKey) {\n credentials.push({\n source: 'aider',\n provider: 'openai',\n authType: 'api-key',\n envVar: 'OPENAI_API_KEY',\n value: openaiKey,\n });\n }\n\n // Gemini API Key (Aider also supports Gemini)\n const geminiKey = process.env.GEMINI_API_KEY;\n if (geminiKey) {\n credentials.push({\n source: 'aider',\n provider: 'google',\n authType: 'api-key',\n envVar: 'GEMINI_API_KEY',\n value: geminiKey,\n });\n }\n\n return credentials;\n}\n\n// =============================================================================\n// Environment Variable Detection\n// =============================================================================\n\n/**\n * Detect credentials from standard environment variables\n */\nexport async function detectEnvAuth(): Promise<DetectedCredential[]> {\n const credentials: DetectedCredential[] = [];\n\n const envMappings: Array<{\n envVar: string;\n provider: 'anthropic' | 'openai' | 'google';\n }> = [\n { envVar: 'ANTHROPIC_API_KEY', provider: 'anthropic' },\n { envVar: 'OPENAI_API_KEY', provider: 'openai' },\n { envVar: 'GEMINI_API_KEY', provider: 'google' },\n { envVar: 'GOOGLE_API_KEY', provider: 'google' },\n ];\n\n for (const { envVar, provider } of envMappings) {\n const value = process.env[envVar];\n if (value) {\n credentials.push({\n source: 'env',\n provider,\n authType: 'api-key',\n envVar,\n value,\n });\n }\n }\n\n return credentials;\n}\n\n// =============================================================================\n// Main Detection Functions\n// =============================================================================\n\n/**\n * Detect all available credentials from external sources\n */\nexport async function detectAllCredentials(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<DetectedCredential[]> {\n if (!config.enabled) {\n return [];\n }\n\n const sources = config.sources || DEFAULT_CONFIG.sources!;\n const credentials: DetectedCredential[] = [];\n const seenValues = new Set<string>();\n\n for (const source of sources) {\n try {\n let detected: DetectedCredential | DetectedCredential[] | null = null;\n\n switch (source) {\n case 'claude-code':\n detected = await detectClaudeCodeAuth();\n break;\n case 'codex':\n detected = await detectCodexAuth();\n break;\n case 'gemini-cli':\n detected = await detectGeminiAuth();\n break;\n case 'aider':\n detected = await detectAiderAuth();\n break;\n case 'env':\n detected = await detectEnvAuth();\n break;\n }\n\n if (detected) {\n const items = Array.isArray(detected) ? detected : [detected];\n for (const item of items) {\n // Deduplicate by value to avoid listing the same API key multiple times\n const key = item.value || item.envVar || '';\n if (key && !seenValues.has(key)) {\n seenValues.add(key);\n credentials.push(item);\n }\n }\n }\n } catch (error) {\n logger.debug(`Error detecting ${source} credentials:`, error);\n }\n }\n\n return credentials;\n}\n\n/**\n * Get authentication status summary\n */\nexport async function getAuthStatus(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<AuthStatus> {\n const credentials = await detectAllCredentials(config);\n const warnings: string[] = [];\n\n // Check for expired tokens\n for (const cred of credentials) {\n if (cred.expiresAt && cred.expiresAt < new Date()) {\n warnings.push(`${cred.source} OAuth token has expired. Please re-authenticate.`);\n }\n }\n\n // Find preferred source\n let preferredSource: DetectedCredential | undefined;\n if (config.preferSource) {\n preferredSource = credentials.find((c) => c.source === config.preferSource);\n }\n\n // If no preferred source specified, prioritize OAuth over API keys\n if (!preferredSource && credentials.length > 0) {\n preferredSource = credentials.find((c) => c.authType === 'oauth') || credentials[0];\n }\n\n const result: AuthStatus = {\n authenticated: credentials.length > 0,\n sources: credentials,\n };\n\n if (preferredSource) {\n result.preferredSource = preferredSource;\n }\n\n if (warnings.length > 0) {\n result.warnings = warnings;\n }\n\n return result;\n}\n\n/**\n * Get credentials for a specific provider\n */\nexport async function getCredentialsForProvider(\n provider: 'anthropic' | 'openai' | 'google',\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<DetectedCredential | null> {\n const credentials = await detectAllCredentials(config);\n const providerCreds = credentials.filter((c) => c.provider === provider);\n\n if (providerCreds.length === 0) {\n return null;\n }\n\n // Prefer OAuth over API keys\n const found = providerCreds.find((c) => c.authType === 'oauth');\n return found || providerCreds[0] || null;\n}\n\n/**\n * Get environment variables to inject based on detected credentials\n */\nexport async function getAuthEnvironment(\n config: ExternalAuthConfig = DEFAULT_CONFIG\n): Promise<Record<string, string>> {\n const credentials = await detectAllCredentials(config);\n const env: Record<string, string> = {};\n\n // Group by provider and prefer OAuth tokens\n const byProvider = new Map<string, DetectedCredential>();\n\n for (const cred of credentials) {\n const existing = byProvider.get(cred.provider);\n // Prefer OAuth over API keys\n if (!existing || (cred.authType === 'oauth' && existing.authType !== 'oauth')) {\n byProvider.set(cred.provider, cred);\n }\n }\n\n // Map to environment variables\n for (const [provider, cred] of byProvider) {\n if (!cred.value) continue;\n\n switch (provider) {\n case 'anthropic':\n // For OAuth tokens, we use ANTHROPIC_AUTH_TOKEN\n // For API keys, we use ANTHROPIC_API_KEY\n if (cred.authType === 'oauth') {\n env['ANTHROPIC_AUTH_TOKEN'] = cred.value;\n } else {\n env['ANTHROPIC_API_KEY'] = cred.value;\n }\n break;\n\n case 'openai':\n if (cred.authType === 'oauth') {\n // OpenAI Codex uses a different auth header for OAuth\n env['OPENAI_AUTH_TOKEN'] = cred.value;\n } else {\n env['OPENAI_API_KEY'] = cred.value;\n }\n break;\n\n case 'google':\n if (cred.authType === 'oauth') {\n env['GOOGLE_AUTH_TOKEN'] = cred.value;\n } else {\n // Prefer GEMINI_API_KEY, fallback to GOOGLE_API_KEY\n if (cred.envVar === 'GOOGLE_API_KEY') {\n env['GOOGLE_API_KEY'] = cred.value;\n } else {\n env['GEMINI_API_KEY'] = cred.value;\n }\n }\n break;\n }\n }\n\n return env;\n}\n\n/**\n * Format auth status for display\n */\nexport function formatAuthStatus(status: AuthStatus): string {\n const lines: string[] = [];\n\n if (!status.authenticated) {\n lines.push('No authentication detected');\n lines.push('');\n lines.push('To authenticate, either:');\n lines.push(' - Log in with Claude Code: claude');\n lines.push(' - Log in with Codex: codex');\n lines.push(' - Log in with Gemini CLI: gemini');\n lines.push(' - Set environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)');\n return lines.join('\\n');\n }\n\n lines.push('Detected authentication sources:');\n lines.push('');\n\n for (const cred of status.sources) {\n const isPrimary = cred === status.preferredSource;\n const prefix = isPrimary ? '* ' : ' ';\n const authType = cred.authType === 'oauth' ? 'OAuth' : 'API Key';\n\n let line = `${prefix}${cred.source} (${cred.provider}, ${authType})`;\n\n if (cred.accountInfo?.email) {\n line += ` - ${cred.accountInfo.email}`;\n }\n if (cred.accountInfo?.plan) {\n line += ` [${cred.accountInfo.plan}]`;\n }\n if (cred.expiresAt) {\n const expiresIn = Math.round((cred.expiresAt.getTime() - Date.now()) / 1000 / 60);\n if (expiresIn > 0) {\n line += ` (expires in ${expiresIn}m)`;\n } else {\n line += ' (EXPIRED)';\n }\n }\n\n lines.push(line);\n }\n\n if (status.warnings && status.warnings.length > 0) {\n lines.push('');\n lines.push('Warnings:');\n for (const warning of status.warnings) {\n lines.push(` ! ${warning}`);\n }\n }\n\n return lines.join('\\n');\n}\n","/**\n * Logging utilities\n */\n\nimport chalk from 'chalk';\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet currentLevel: LogLevel = 'info';\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nexport function getLogLevel(): LogLevel {\n return currentLevel;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel];\n}\n\nexport const logger = {\n debug(message: string, ...args: unknown[]): void {\n if (shouldLog('debug')) {\n console.log(chalk.gray(`[debug] ${message}`), ...args);\n }\n },\n\n info(message: string, ...args: unknown[]): void {\n if (shouldLog('info')) {\n console.log(chalk.blue('ℹ'), message, ...args);\n }\n },\n\n success(message: string, ...args: unknown[]): void {\n if (shouldLog('info')) {\n console.log(chalk.green('✓'), message, ...args);\n }\n },\n\n warn(message: string, ...args: unknown[]): void {\n if (shouldLog('warn')) {\n console.log(chalk.yellow('⚠'), message, ...args);\n }\n },\n\n error(message: string, ...args: unknown[]): void {\n if (shouldLog('error')) {\n console.error(chalk.red('✗'), message, ...args);\n }\n },\n\n // Styled output helpers\n brand(text: string): string {\n return chalk.hex('#818cf8')(text);\n },\n\n dim(text: string): string {\n return chalk.dim(text);\n },\n\n bold(text: string): string {\n return chalk.bold(text);\n },\n\n // Print a header\n header(text: string): void {\n console.log();\n console.log(chalk.bold(text));\n console.log(chalk.dim('─'.repeat(text.length)));\n },\n\n // Print a blank line\n blank(): void {\n console.log();\n },\n};\n","/**\n * Container management utilities\n * Uses devcontainer CLI for container lifecycle\n */\n\nimport { execa, type ExecaError } from 'execa';\nimport which from 'which';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RapidConfig } from './types.js';\n\nexport interface ContainerStatus {\n exists: boolean;\n running: boolean;\n containerId?: string;\n containerName?: string;\n}\n\nexport interface DevcontainerConfig {\n name?: string;\n image?: string;\n dockerFile?: string;\n build?: {\n dockerfile?: string;\n context?: string;\n };\n [key: string]: unknown;\n}\n\n/**\n * Check if devcontainer CLI is available\n */\nexport async function hasDevcontainerCli(): Promise<boolean> {\n try {\n await which('devcontainer');\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if Docker is available\n */\nexport async function hasDocker(): Promise<boolean> {\n try {\n await execa('docker', ['info'], { timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the devcontainer.json path\n */\nexport function getDevcontainerPath(rootDir: string, config?: RapidConfig): string {\n const customPath = config?.container?.devcontainer;\n if (customPath) {\n return join(rootDir, customPath);\n }\n return join(rootDir, '.devcontainer', 'devcontainer.json');\n}\n\n/**\n * Load devcontainer.json\n */\nexport async function loadDevcontainerConfig(\n rootDir: string,\n config?: RapidConfig\n): Promise<DevcontainerConfig | null> {\n try {\n const configPath = getDevcontainerPath(rootDir, config);\n const content = await readFile(configPath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * Get container name for a project\n */\nexport function getContainerName(rootDir: string, devcontainerConfig?: DevcontainerConfig): string {\n // Use devcontainer name if available, otherwise derive from directory\n const dirName = rootDir.split('/').pop() || 'rapid';\n const name = devcontainerConfig?.name || dirName;\n // Sanitize for Docker container name\n return `rapid-${name}`.toLowerCase().replace(/[^a-z0-9-]/g, '-');\n}\n\n/**\n * Check container status using devcontainer labels\n */\nexport async function getContainerStatus(\n rootDir: string,\n _config?: RapidConfig\n): Promise<ContainerStatus> {\n try {\n // Use devcontainer label to find the container (this is how devcontainer CLI tracks containers)\n const result = await execa('docker', [\n 'ps',\n '-a',\n '--filter',\n `label=devcontainer.local_folder=${rootDir}`,\n '--format',\n '{{.ID}}\\t{{.State}}\\t{{.Names}}',\n ]);\n\n const lines = result.stdout.trim().split('\\n').filter(Boolean);\n if (lines.length === 0) {\n return { exists: false, running: false };\n }\n\n const parts = lines[0]?.split('\\t');\n const containerId = parts?.[0];\n const state = parts?.[1];\n const containerName = parts?.[2];\n\n if (!containerId || !containerName) {\n return { exists: false, running: false };\n }\n\n return {\n exists: true,\n running: state === 'running',\n containerId,\n containerName,\n };\n } catch {\n return { exists: false, running: false };\n }\n}\n\n/**\n * Start the dev container using devcontainer CLI\n */\nexport async function startContainer(\n rootDir: string,\n _config?: RapidConfig,\n options: { rebuild?: boolean; quiet?: boolean } = {}\n): Promise<{ success: boolean; containerId?: string; error?: string }> {\n const hasDevCli = await hasDevcontainerCli();\n\n if (!hasDevCli) {\n return {\n success: false,\n error: 'devcontainer CLI not found. Install with: npm install -g @devcontainers/cli',\n };\n }\n\n const hasDockerRunning = await hasDocker();\n if (!hasDockerRunning) {\n return {\n success: false,\n error: 'Docker is not running. Please start Docker Desktop.',\n };\n }\n\n try {\n const args = ['up', '--workspace-folder', rootDir];\n\n if (options.rebuild) {\n args.push('--remove-existing-container');\n }\n\n const result = await execa('devcontainer', args, {\n stdio: options.quiet ? 'pipe' : 'inherit',\n cwd: rootDir,\n });\n\n // Parse the container ID from output\n // devcontainer up outputs JSON with containerId\n if (options.quiet && result.stdout) {\n try {\n const output = JSON.parse(result.stdout);\n return { success: true, containerId: output.containerId };\n } catch {\n return { success: true };\n }\n }\n\n return { success: true };\n } catch (error) {\n const execError = error as ExecaError;\n const stderr = typeof execError.stderr === 'string' ? execError.stderr : undefined;\n return {\n success: false,\n error: stderr || execError.message,\n };\n }\n}\n\n/**\n * Stop the dev container\n */\nexport async function stopContainer(\n rootDir: string,\n config?: RapidConfig,\n options: { remove?: boolean } = {}\n): Promise<{ success: boolean; error?: string }> {\n const status = await getContainerStatus(rootDir, config);\n\n if (!status.exists) {\n return { success: true }; // Nothing to stop\n }\n\n try {\n if (status.running) {\n await execa('docker', ['stop', status.containerId!]);\n }\n\n if (options.remove) {\n await execa('docker', ['rm', status.containerId!]);\n }\n\n return { success: true };\n } catch (error) {\n const execError = error as ExecaError;\n const stderr = typeof execError.stderr === 'string' ? execError.stderr : undefined;\n return {\n success: false,\n error: stderr || execError.message,\n };\n }\n}\n\n/**\n * Execute a command inside the dev container\n */\nexport async function execInContainer(\n rootDir: string,\n command: string[],\n _config?: RapidConfig,\n options: { interactive?: boolean; tty?: boolean; env?: Record<string, string> } = {}\n): Promise<void> {\n const hasDevCli = await hasDevcontainerCli();\n\n if (!hasDevCli) {\n throw new Error('devcontainer CLI not found. Install with: npm install -g @devcontainers/cli');\n }\n\n const args = ['exec', '--workspace-folder', rootDir];\n\n // Add environment variables\n if (options.env) {\n for (const [key, value] of Object.entries(options.env)) {\n args.push('--remote-env', `${key}=${value}`);\n }\n }\n\n // Add the command\n args.push(...command);\n\n await execa('devcontainer', args, {\n stdio: 'inherit',\n cwd: rootDir,\n });\n}\n","/**\n * Secrets management for RAPID\n * Supports 1Password, HashiCorp Vault, and environment variables\n */\n\nimport { spawn } from 'node:child_process';\nimport { readFile, writeFile, access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { SecretsConfig } from './types.js';\nimport { logger } from './logger.js';\n\nexport interface SecretStatus {\n name: string;\n reference: string;\n provider: 'env' | '1password' | 'vault';\n available: boolean;\n error?: string;\n}\n\nexport interface SecretsStatus {\n provider: 'env' | '1password' | 'vault';\n authenticated: boolean;\n authMethod?: 'service-account' | 'user' | 'token';\n secrets: SecretStatus[];\n allAvailable: boolean;\n}\n\nexport interface OpAuthStatus {\n authenticated: boolean;\n method: 'service-account' | 'user' | 'none';\n accountInfo?: string;\n}\n\n/**\n * Execute a command and return stdout\n */\nasync function execCommand(\n command: string,\n args: string[],\n options: { timeout?: number } = {}\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: options.timeout ?? 30000,\n });\n\n let stdout = '';\n let stderr = '';\n\n proc.stdout?.on('data', (data) => {\n stdout += data.toString();\n });\n\n proc.stderr?.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.on('close', (code) => {\n resolve({ stdout: stdout.trim(), stderr: stderr.trim(), exitCode: code ?? 1 });\n });\n\n proc.on('error', (err) => {\n resolve({ stdout: '', stderr: err.message, exitCode: 1 });\n });\n });\n}\n\n/**\n * Check if 1Password CLI is installed\n */\nexport async function hasOpCli(): Promise<boolean> {\n const result = await execCommand('op', ['--version']);\n return result.exitCode === 0;\n}\n\n/**\n * Check if OP_SERVICE_ACCOUNT_TOKEN is set\n */\nexport function hasOpServiceAccountToken(): boolean {\n return !!process.env.OP_SERVICE_ACCOUNT_TOKEN;\n}\n\n/**\n * Check if 1Password CLI is authenticated (via service account or user)\n */\nexport async function isOpAuthenticated(): Promise<boolean> {\n // Service account token takes precedence\n if (hasOpServiceAccountToken()) {\n // Verify the token works by trying to list vaults\n const result = await execCommand('op', ['vault', 'list', '--format=json']);\n return result.exitCode === 0;\n }\n\n // Fall back to user authentication\n const result = await execCommand('op', ['account', 'list']);\n return result.exitCode === 0 && result.stdout.length > 0;\n}\n\n/**\n * Get detailed 1Password authentication status\n */\nexport async function getOpAuthStatus(): Promise<OpAuthStatus> {\n // Check for service account token first\n if (hasOpServiceAccountToken()) {\n const result = await execCommand('op', ['vault', 'list', '--format=json']);\n if (result.exitCode === 0) {\n return {\n authenticated: true,\n method: 'service-account',\n accountInfo: 'Service Account',\n };\n }\n return {\n authenticated: false,\n method: 'none',\n accountInfo: 'Invalid service account token',\n };\n }\n\n // Check for user authentication\n const result = await execCommand('op', ['account', 'list', '--format=json']);\n if (result.exitCode === 0 && result.stdout.length > 0) {\n try {\n const accounts = JSON.parse(result.stdout);\n if (accounts.length > 0) {\n return {\n authenticated: true,\n method: 'user',\n accountInfo: accounts[0].email || accounts[0].url,\n };\n }\n } catch {\n // Parse error, but command succeeded\n return {\n authenticated: true,\n method: 'user',\n };\n }\n }\n\n return {\n authenticated: false,\n method: 'none',\n };\n}\n\n/**\n * Check if HashiCorp Vault CLI is installed\n */\nexport async function hasVaultCli(): Promise<boolean> {\n const result = await execCommand('vault', ['--version']);\n return result.exitCode === 0;\n}\n\n/**\n * Check if HashiCorp Vault is authenticated\n */\nexport async function isVaultAuthenticated(): Promise<boolean> {\n const result = await execCommand('vault', ['token', 'lookup']);\n return result.exitCode === 0;\n}\n\n/**\n * Read a secret from 1Password\n * @param reference - 1Password reference (e.g., \"op://vault/item/field\")\n */\nexport async function readOpSecret(reference: string): Promise<string | null> {\n const result = await execCommand('op', ['read', reference]);\n if (result.exitCode !== 0) {\n return null;\n }\n return result.stdout;\n}\n\n/**\n * Read a secret from HashiCorp Vault\n * @param path - Vault path (e.g., \"secret/data/myproject\")\n * @param field - Field name within the secret\n */\nexport async function readVaultSecret(path: string, field: string): Promise<string | null> {\n const result = await execCommand('vault', ['kv', 'get', '-field', field, path]);\n if (result.exitCode !== 0) {\n return null;\n }\n return result.stdout;\n}\n\n/**\n * Verify a single secret is accessible\n */\nexport async function verifySecret(\n name: string,\n reference: string,\n provider: 'env' | '1password' | 'vault',\n config?: SecretsConfig\n): Promise<SecretStatus> {\n const status: SecretStatus = {\n name,\n reference,\n provider,\n available: false,\n };\n\n try {\n switch (provider) {\n case 'env': {\n const value = process.env[name];\n status.available = !!value && value.length > 0;\n if (!status.available) {\n status.error = 'Environment variable not set';\n }\n break;\n }\n\n case '1password': {\n // Reference should be in format op://vault/item/field\n const value = await readOpSecret(reference);\n status.available = value !== null;\n if (!status.available) {\n status.error = 'Secret not found in 1Password';\n }\n break;\n }\n\n case 'vault': {\n // Parse path and field from reference\n const field = reference.split('/').pop() || 'value';\n const vaultPath = reference.includes('/')\n ? reference.substring(0, reference.lastIndexOf('/'))\n : config?.vault || 'secret/data/default';\n\n const value = await readVaultSecret(vaultPath, field);\n status.available = value !== null;\n if (!status.available) {\n status.error = 'Secret not found in Vault';\n }\n break;\n }\n }\n } catch (error) {\n status.error = error instanceof Error ? error.message : String(error);\n status.available = false;\n }\n\n return status;\n}\n\n/**\n * Verify all secrets in configuration\n */\nexport async function verifySecrets(config: SecretsConfig): Promise<SecretsStatus> {\n const provider = config.provider || 'env';\n let authenticated = true;\n\n // Check authentication status for provider\n switch (provider) {\n case '1password':\n authenticated = await isOpAuthenticated();\n break;\n case 'vault':\n authenticated = await isVaultAuthenticated();\n break;\n case 'env':\n authenticated = true;\n break;\n }\n\n const secrets: SecretStatus[] = [];\n\n if (config.items) {\n for (const [name, reference] of Object.entries(config.items)) {\n const status = await verifySecret(name, reference, provider, config);\n secrets.push(status);\n }\n }\n\n const allAvailable = secrets.length === 0 || secrets.every((s) => s.available);\n\n return {\n provider,\n authenticated,\n secrets,\n allAvailable,\n };\n}\n\n/**\n * Load all secrets into environment\n */\nexport async function loadSecrets(config: SecretsConfig): Promise<Record<string, string>> {\n const provider = config.provider || 'env';\n const secrets: Record<string, string> = {};\n\n if (!config.items) {\n return secrets;\n }\n\n for (const [name, reference] of Object.entries(config.items)) {\n try {\n let value: string | null = null;\n\n switch (provider) {\n case 'env':\n value = process.env[name] || null;\n break;\n\n case '1password':\n value = await readOpSecret(reference);\n break;\n\n case 'vault': {\n const field = reference.split('/').pop() || 'value';\n const path = reference.substring(0, reference.lastIndexOf('/')) || config.vault || '';\n value = await readVaultSecret(path, field);\n break;\n }\n }\n\n if (value) {\n secrets[name] = value;\n }\n } catch (error) {\n logger.debug(`Failed to load secret ${name}: ${error}`);\n }\n }\n\n return secrets;\n}\n\n/**\n * Generate .envrc file from secrets configuration\n */\nexport function generateEnvrc(config: SecretsConfig): string {\n const provider = config.provider || 'env';\n const lines: string[] = [\n '# .envrc - RAPID project secrets',\n '# This file is safe to commit - it contains NO secrets, only references',\n '#',\n `# Provider: ${provider}`,\n `# Generated by: rapid secrets generate`,\n '',\n ];\n\n if (!config.items || Object.keys(config.items).length === 0) {\n lines.push('# No secrets configured in rapid.json');\n return lines.join('\\n');\n }\n\n switch (provider) {\n case '1password':\n lines.push('# Secrets loaded from 1Password');\n lines.push('# Requires: 1Password CLI (op) installed and authenticated');\n lines.push('');\n for (const [name, reference] of Object.entries(config.items)) {\n lines.push(`export ${name}=$(op read \"${reference}\")`);\n }\n break;\n\n case 'vault':\n lines.push('# Secrets loaded from HashiCorp Vault');\n lines.push('# Requires: Vault CLI installed and authenticated');\n lines.push('');\n if (config.address) {\n lines.push(`export VAULT_ADDR=\"${config.address}\"`);\n lines.push('');\n }\n for (const [name, reference] of Object.entries(config.items)) {\n const path = config.vault || 'secret/data/default';\n lines.push(`export ${name}=$(vault kv get -field=${reference} ${path})`);\n }\n break;\n\n case 'env':\n lines.push('# WARNING: env provider expects secrets to be set manually');\n lines.push('# Consider using 1password or vault for better security');\n lines.push('');\n lines.push('# Uncomment and set values (DO NOT commit actual values!)');\n for (const name of Object.keys(config.items)) {\n lines.push(`# export ${name}=\"your-value-here\"`);\n }\n break;\n }\n\n // Add .env.local loading if configured\n if (config.envrc?.includeLocal !== false) {\n lines.push('');\n lines.push('# Load local overrides if present');\n lines.push('[[ -f .env.local ]] && source_env .env.local');\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Write .envrc file to project directory\n */\nexport async function writeEnvrc(rootDir: string, config: SecretsConfig): Promise<string> {\n const envrcPath = config.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n const content = generateEnvrc(config);\n\n await writeFile(fullPath, content);\n return fullPath;\n}\n\n/**\n * Check if .envrc exists in project\n */\nexport async function hasEnvrc(rootDir: string, config?: SecretsConfig): Promise<boolean> {\n const envrcPath = config?.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n\n try {\n await access(fullPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read existing .envrc content\n */\nexport async function readEnvrc(rootDir: string, config?: SecretsConfig): Promise<string | null> {\n const envrcPath = config?.envrc?.path || '.envrc';\n const fullPath = join(rootDir, envrcPath);\n\n try {\n const content = await readFile(fullPath, 'utf-8');\n return content;\n } catch {\n return null;\n }\n}\n\n/**\n * Get a summary of provider requirements\n */\nexport function getProviderInfo(provider: 'env' | '1password' | 'vault'): {\n name: string;\n cliRequired: string | null;\n authCommand: string | null;\n installUrl: string | null;\n} {\n switch (provider) {\n case '1password':\n return {\n name: '1Password',\n cliRequired: 'op',\n authCommand: 'eval $(op signin)',\n installUrl: 'https://developer.1password.com/docs/cli/get-started/',\n };\n case 'vault':\n return {\n name: 'HashiCorp Vault',\n cliRequired: 'vault',\n authCommand: 'vault login',\n installUrl: 'https://developer.hashicorp.com/vault/docs/install',\n };\n case 'env':\n return {\n name: 'Environment Variables',\n cliRequired: null,\n authCommand: null,\n installUrl: null,\n };\n }\n}\n","/**\n * MCP Server Management\n *\n * Functions for managing Model Context Protocol servers in RAPID configuration.\n */\n\nimport { writeFile, readFile, access } from 'node:fs/promises';\nimport { join, isAbsolute } from 'node:path';\nimport type { RapidConfig, McpServerConfig } from './types.js';\nimport { getMcpTemplate } from './mcp-templates.js';\n\n/**\n * Extended MCP server configuration with type-safe properties\n */\nexport interface McpServerDefinition extends McpServerConfig {\n enabled?: boolean;\n type?: 'remote' | 'stdio';\n url?: string;\n headers?: Record<string, string>;\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n}\n\n/**\n * MCP server info for display\n */\nexport interface McpServerInfo {\n name: string;\n enabled: boolean;\n type: 'remote' | 'stdio';\n url?: string | undefined;\n command?: string | undefined;\n template?: string | undefined;\n}\n\n/**\n * MCP server status\n */\nexport interface McpServerStatus extends McpServerInfo {\n status: 'enabled' | 'disabled' | 'error';\n error?: string | undefined;\n}\n\n/**\n * Generated MCP config file format (for .mcp.json)\n */\nexport interface GeneratedMcpConfig {\n mcpServers: Record<string, McpServerEntry>;\n}\n\n/**\n * Single server entry in generated config\n */\nexport interface McpServerEntry {\n type?: 'http' | 'stdio';\n url?: string | undefined;\n headers?: Record<string, string> | undefined;\n command?: string | undefined;\n args?: string[] | undefined;\n env?: Record<string, string> | undefined;\n}\n\n/**\n * OpenCode config format\n */\nexport interface OpenCodeConfig {\n $schema?: string;\n mcp?: Record<string, OpenCodeMcpEntry>;\n}\n\n/**\n * OpenCode MCP entry format\n */\nexport interface OpenCodeMcpEntry {\n type: 'remote' | 'stdio';\n url?: string | undefined;\n headers?: Record<string, string> | undefined;\n command?: string | undefined;\n args?: string[] | undefined;\n env?: Record<string, string> | undefined;\n}\n\n/**\n * Get all configured MCP servers from config\n */\nexport function getMcpServers(config: RapidConfig): McpServerInfo[] {\n const servers: McpServerInfo[] = [];\n\n if (!config.mcp?.servers) {\n return servers;\n }\n\n for (const [name, serverConfig] of Object.entries(config.mcp.servers)) {\n if (!serverConfig || typeof serverConfig !== 'object') {\n continue;\n }\n\n const def = serverConfig as McpServerDefinition;\n const template = getMcpTemplate(name);\n\n servers.push({\n name,\n enabled: def.enabled !== false,\n type: def.type ?? template?.type ?? 'stdio',\n url: def.url ?? template?.url,\n command: def.command ?? template?.command,\n template: template ? name : undefined,\n });\n }\n\n return servers;\n}\n\n/**\n * Get MCP server status for all configured servers\n */\nexport function getMcpServerStatus(config: RapidConfig): McpServerStatus[] {\n const servers = getMcpServers(config);\n\n return servers.map((server) => ({\n ...server,\n status: server.enabled ? ('enabled' as const) : ('disabled' as const),\n }));\n}\n\n/**\n * Add an MCP server to configuration\n */\nexport function addMcpServer(\n config: RapidConfig,\n name: string,\n serverConfig: McpServerDefinition\n): RapidConfig {\n return {\n ...config,\n mcp: {\n ...config.mcp,\n configFile: config.mcp?.configFile ?? '.mcp.json',\n servers: {\n ...config.mcp?.servers,\n [name]: serverConfig,\n },\n },\n };\n}\n\n/**\n * Add an MCP server from a template\n */\nexport function addMcpServerFromTemplate(config: RapidConfig, templateName: string): RapidConfig {\n const template = getMcpTemplate(templateName);\n if (!template) {\n throw new Error(`Unknown MCP server template: ${templateName}`);\n }\n\n const serverConfig: McpServerDefinition = {\n enabled: true,\n type: template.type,\n };\n\n // Add type-specific config\n if (template.type === 'remote') {\n if (template.url) {\n serverConfig.url = template.url;\n }\n if (template.headers) {\n serverConfig.headers = { ...template.headers };\n }\n } else {\n if (template.command) {\n serverConfig.command = template.command;\n }\n if (template.args) {\n serverConfig.args = [...template.args];\n }\n if (template.env) {\n serverConfig.env = { ...template.env };\n }\n }\n\n return addMcpServer(config, templateName, serverConfig);\n}\n\n/**\n * Remove an MCP server from configuration\n */\nexport function removeMcpServer(config: RapidConfig, name: string): RapidConfig {\n if (!config.mcp?.servers?.[name]) {\n throw new Error(`MCP server not found: ${name}`);\n }\n\n const { [name]: _removed, ...remainingServers } = config.mcp.servers;\n\n return {\n ...config,\n mcp: {\n ...config.mcp,\n servers: remainingServers,\n },\n };\n}\n\n/**\n * Enable an MCP server\n */\nexport function enableMcpServer(config: RapidConfig, name: string): RapidConfig {\n if (!config.mcp?.servers?.[name]) {\n throw new Error(`MCP server not found: ${name}`);\n }\n\n return {\n ...config,\n mcp: {\n ...config.mcp,\n servers: {\n ...config.mcp.servers,\n [name]: {\n ...config.mcp.servers[name],\n enabled: true,\n },\n },\n },\n };\n}\n\n/**\n * Disable an MCP server\n */\nexport function disableMcpServer(config: RapidConfig, name: string): RapidConfig {\n if (!config.mcp?.servers?.[name]) {\n throw new Error(`MCP server not found: ${name}`);\n }\n\n return {\n ...config,\n mcp: {\n ...config.mcp,\n servers: {\n ...config.mcp.servers,\n [name]: {\n ...config.mcp.servers[name],\n enabled: false,\n },\n },\n },\n };\n}\n\n/**\n * Generate .mcp.json config from rapid.json mcp section\n */\nexport function generateMcpConfig(config: RapidConfig): GeneratedMcpConfig {\n const mcpServers: Record<string, McpServerEntry> = {};\n\n if (!config.mcp?.servers) {\n return { mcpServers };\n }\n\n for (const [name, serverConfig] of Object.entries(config.mcp.servers)) {\n if (!serverConfig || typeof serverConfig !== 'object') {\n continue;\n }\n\n const def = serverConfig as McpServerDefinition;\n\n // Skip disabled servers\n if (def.enabled === false) {\n continue;\n }\n\n // Get template for defaults\n const template = getMcpTemplate(name);\n\n const entry: McpServerEntry = {};\n\n // Determine type\n const type = def.type ?? template?.type ?? 'stdio';\n\n if (type === 'remote') {\n entry.type = 'http';\n entry.url = def.url ?? template?.url;\n entry.headers = def.headers ?? template?.headers;\n } else {\n entry.type = 'stdio';\n entry.command = def.command ?? template?.command;\n entry.args = def.args ?? template?.args;\n if (def.env ?? template?.env) {\n entry.env = { ...template?.env, ...def.env };\n }\n }\n\n mcpServers[name] = entry;\n }\n\n return { mcpServers };\n}\n\n/**\n * Generate opencode.json config format\n */\nexport function generateOpenCodeConfig(config: RapidConfig): OpenCodeConfig {\n const mcp: Record<string, OpenCodeMcpEntry> = {};\n\n if (!config.mcp?.servers) {\n return { $schema: 'https://opencode.ai/config.json', mcp };\n }\n\n for (const [name, serverConfig] of Object.entries(config.mcp.servers)) {\n if (!serverConfig || typeof serverConfig !== 'object') {\n continue;\n }\n\n const def = serverConfig as McpServerDefinition;\n\n // Skip disabled servers\n if (def.enabled === false) {\n continue;\n }\n\n // Get template for defaults\n const template = getMcpTemplate(name);\n\n const type = def.type ?? template?.type ?? 'stdio';\n\n const entry: OpenCodeMcpEntry = {\n type: type,\n };\n\n if (type === 'remote') {\n entry.url = def.url ?? template?.url;\n const headers = def.headers ?? template?.headers;\n if (headers) {\n // OpenCode uses {env:VAR} format instead of ${VAR}\n entry.headers = {};\n for (const [key, value] of Object.entries(headers)) {\n entry.headers[key] = value.replace(/\\$\\{(\\w+)\\}/g, '{env:$1}');\n }\n }\n } else {\n entry.command = def.command ?? template?.command;\n entry.args = def.args ?? template?.args;\n if (def.env ?? template?.env) {\n entry.env = { ...template?.env, ...def.env };\n }\n }\n\n mcp[name] = entry;\n }\n\n return { $schema: 'https://opencode.ai/config.json', mcp };\n}\n\n/**\n * Write .mcp.json file\n */\nexport async function writeMcpConfig(rootDir: string, config: RapidConfig): Promise<void> {\n const mcpConfig = generateMcpConfig(config);\n const configFile = config.mcp?.configFile ?? '.mcp.json';\n const configPath = isAbsolute(configFile) ? configFile : join(rootDir, configFile);\n\n await writeFile(configPath, JSON.stringify(mcpConfig, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Write opencode.json file\n */\nexport async function writeOpenCodeConfig(rootDir: string, config: RapidConfig): Promise<void> {\n const openCodeConfig = generateOpenCodeConfig(config);\n const configPath = join(rootDir, 'opencode.json');\n\n await writeFile(configPath, JSON.stringify(openCodeConfig, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Check if .mcp.json exists\n */\nexport async function hasMcpConfig(rootDir: string, config?: RapidConfig): Promise<boolean> {\n const configFile = config?.mcp?.configFile ?? '.mcp.json';\n const configPath = isAbsolute(configFile) ? configFile : join(rootDir, configFile);\n\n try {\n await access(configPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read existing .mcp.json file\n */\nexport async function readMcpConfig(\n rootDir: string,\n config?: RapidConfig\n): Promise<GeneratedMcpConfig | null> {\n const configFile = config?.mcp?.configFile ?? '.mcp.json';\n const configPath = isAbsolute(configFile) ? configFile : join(rootDir, configFile);\n\n try {\n const content = await readFile(configPath, 'utf-8');\n return JSON.parse(content) as GeneratedMcpConfig;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the MCP config file path for environment variable\n */\nexport function getMcpConfigPath(rootDir: string, config?: RapidConfig): string {\n const configFile = config?.mcp?.configFile ?? '.mcp.json';\n return isAbsolute(configFile) ? configFile : join(rootDir, configFile);\n}\n\n// Re-export template functions\nexport {\n MCP_SERVER_TEMPLATES,\n getMcpTemplate,\n getMcpTemplateNames,\n getEasySetupTemplates,\n getRequiredSecrets,\n getSecretReferences,\n type McpServerTemplate,\n} from './mcp-templates.js';\n","/**\n * Built-in MCP Server Templates\n *\n * Predefined configurations for popular MCP servers that can be\n * selected during `rapid init` or added via `rapid mcp add`.\n */\n\n/**\n * MCP server template definition\n */\nexport interface McpServerTemplate {\n /** Display name */\n name: string;\n /** Short description */\n description: string;\n /** Server type: remote HTTP or local stdio */\n type: 'remote' | 'stdio';\n /** URL for remote servers */\n url?: string;\n /** HTTP headers for remote servers (supports ${VAR} substitution) */\n headers?: Record<string, string>;\n /** Command for stdio servers */\n command?: string;\n /** Arguments for stdio command */\n args?: string[];\n /** Environment variables for stdio servers */\n env?: Record<string, string>;\n /** Required secrets (env var names) */\n requiredSecrets: string[];\n /** Hint for obtaining required secrets */\n secretHint?: string;\n /** Default 1Password reference for secrets */\n secretReferences?: Record<string, string>;\n}\n\n/**\n * Built-in MCP server templates\n */\nexport const MCP_SERVER_TEMPLATES: Record<string, McpServerTemplate> = {\n context7: {\n name: 'Context7',\n description: 'Documentation context for libraries and frameworks',\n type: 'remote',\n url: 'https://mcp.context7.com/mcp',\n headers: {\n 'Context7-API-Key': '${CONTEXT7_API_KEY}',\n },\n requiredSecrets: ['CONTEXT7_API_KEY'],\n secretHint: 'Get your API key at https://context7.com',\n secretReferences: {\n CONTEXT7_API_KEY: 'op://Development/Context7/api-key',\n },\n },\n\n tavily: {\n name: 'Tavily',\n description: 'Web search and data extraction',\n type: 'remote',\n url: 'https://mcp.tavily.com/mcp',\n headers: {\n Authorization: 'Bearer ${TAVILY_API_KEY}',\n },\n requiredSecrets: ['TAVILY_API_KEY'],\n secretHint: 'Get your API key at https://tavily.com',\n secretReferences: {\n TAVILY_API_KEY: 'op://Development/Tavily/api-key',\n },\n },\n\n playwright: {\n name: 'Playwright',\n description: 'Browser automation and web scraping',\n type: 'stdio',\n command: 'npx',\n args: ['@playwright/mcp@latest'],\n requiredSecrets: [],\n },\n\n github: {\n name: 'GitHub',\n description: 'GitHub operations (PRs, issues, repos)',\n type: 'stdio',\n command: 'npx',\n args: ['@modelcontextprotocol/server-github'],\n env: {\n GITHUB_TOKEN: '${GITHUB_TOKEN}',\n },\n requiredSecrets: ['GITHUB_TOKEN'],\n secretHint: 'Create a personal access token at https://github.com/settings/tokens',\n secretReferences: {\n GITHUB_TOKEN: 'op://Development/GitHub/pat',\n },\n },\n\n filesystem: {\n name: 'Filesystem',\n description: 'File system access (read/write/search)',\n type: 'stdio',\n command: 'npx',\n args: ['@modelcontextprotocol/server-filesystem', '.'],\n requiredSecrets: [],\n },\n\n memory: {\n name: 'Memory',\n description: 'Persistent knowledge graph memory',\n type: 'stdio',\n command: 'npx',\n args: ['@modelcontextprotocol/server-memory'],\n requiredSecrets: [],\n },\n\n postgres: {\n name: 'PostgreSQL',\n description: 'PostgreSQL database access',\n type: 'stdio',\n command: 'npx',\n args: ['@modelcontextprotocol/server-postgres'],\n env: {\n DATABASE_URL: '${DATABASE_URL}',\n },\n requiredSecrets: ['DATABASE_URL'],\n secretHint: 'PostgreSQL connection string (e.g., postgres://user:pass@host:5432/db)',\n secretReferences: {\n DATABASE_URL: 'op://Development/PostgreSQL/connection-string',\n },\n },\n\n slack: {\n name: 'Slack',\n description: 'Slack messaging and channel management',\n type: 'stdio',\n command: 'npx',\n args: ['@modelcontextprotocol/server-slack'],\n env: {\n SLACK_TOKEN: '${SLACK_TOKEN}',\n },\n requiredSecrets: ['SLACK_TOKEN'],\n secretHint: 'Create a Slack app and get a bot token at https://api.slack.com/apps',\n secretReferences: {\n SLACK_TOKEN: 'op://Development/Slack/bot-token',\n },\n },\n\n fetch: {\n name: 'Fetch',\n description: 'HTTP fetch for web content retrieval',\n type: 'stdio',\n command: 'npx',\n args: ['@modelcontextprotocol/server-fetch'],\n requiredSecrets: [],\n },\n\n sqlite: {\n name: 'SQLite',\n description: 'SQLite database access',\n type: 'stdio',\n command: 'npx',\n args: ['@modelcontextprotocol/server-sqlite'],\n requiredSecrets: [],\n },\n};\n\n/**\n * Get a template by name\n */\nexport function getMcpTemplate(name: string): McpServerTemplate | undefined {\n return MCP_SERVER_TEMPLATES[name];\n}\n\n/**\n * Get all template names\n */\nexport function getMcpTemplateNames(): string[] {\n return Object.keys(MCP_SERVER_TEMPLATES);\n}\n\n/**\n * Get templates that don't require secrets (easy setup)\n */\nexport function getEasySetupTemplates(): string[] {\n return Object.entries(MCP_SERVER_TEMPLATES)\n .filter(([, template]) => template.requiredSecrets.length === 0)\n .map(([name]) => name);\n}\n\n/**\n * Get all required secrets for a list of template names\n */\nexport function getRequiredSecrets(templateNames: string[]): string[] {\n const secrets = new Set<string>();\n for (const name of templateNames) {\n const template = MCP_SERVER_TEMPLATES[name];\n if (template) {\n for (const secret of template.requiredSecrets) {\n secrets.add(secret);\n }\n }\n }\n return [...secrets];\n}\n\n/**\n * Get all secret references for a list of template names\n */\nexport function getSecretReferences(templateNames: string[]): Record<string, string> {\n const refs: Record<string, string> = {};\n for (const name of templateNames) {\n const template = MCP_SERVER_TEMPLATES[name];\n if (template?.secretReferences) {\n Object.assign(refs, template.secretReferences);\n }\n }\n return refs;\n}\n"],"mappings":"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","names":["readFile","readFile","execa","which","readFile","join","readFile","access","join","resolve","result","join","access","readFile","writeFile","readFile","access","join","join","writeFile","access","readFile"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a3t/rapid-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Core library for RAPID - AI-assisted development with dev containers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Steve Rude <steve@rude.la>",
|
|
@@ -31,20 +31,20 @@
|
|
|
31
31
|
"dist"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"chalk": "^5.
|
|
34
|
+
"chalk": "^5.6.2",
|
|
35
35
|
"cosmiconfig": "^9.0.0",
|
|
36
36
|
"execa": "^9.6.1",
|
|
37
|
-
"which": "^
|
|
37
|
+
"which": "^6.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@types/node": "^
|
|
40
|
+
"@types/node": "^25.0.8",
|
|
41
41
|
"@types/which": "^3.0.4",
|
|
42
42
|
"tsup": "^8.5.1",
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
|
-
"vitest": "^
|
|
44
|
+
"vitest": "^4.0.17"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@a3t/rapid-schema": "0.1.
|
|
47
|
+
"@a3t/rapid-schema": "0.1.5"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "tsup",
|