MCPcopy Create free account
hub / github.com/cortexkit/magic-context / substituteConfigVariables

Function substituteConfigVariables

packages/plugin/src/config/variable.ts:79–192  ·  view source on GitHub ↗
(input: SubstituteInput)

Source from the content-addressed store, hash-verified

77 * the subsequent JSONC parse.
78 */
79export function substituteConfigVariables(input: SubstituteInput): SubstituteResult {
80 const warnings: string[] = [];
81 let text = input.text;
82
83 if (input.isProjectConfig) {
84 const hasEnvTokens = ENV_PATTERN.test(text);
85 const hasFileTokens = FILE_PATTERN.test(text);
86 ENV_PATTERN.lastIndex = 0;
87 FILE_PATTERN.lastIndex = 0;
88 if (hasEnvTokens || hasFileTokens) {
89 const tokenTypes = [
90 hasEnvTokens ? "{env:}" : undefined,
91 hasFileTokens ? "{file:}" : undefined,
92 ]
93 .filter(Boolean)
94 .join(" and ");
95 warnings.push(
96 `Project-level config no longer supports ${tokenTypes} tokens for security reasons; leaving tokens literal. Move secret expansion to user-level config.`,
97 );
98 }
99 return { text, warnings };
100 }
101
102 // Strip JSONC comments before substitution so tokens in comments cannot
103 // trigger env/file side effects. The shared parser helper is string-aware,
104 // so URL strings and literal comment markers inside strings are preserved.
105 text = stripJsonComments(text);
106
107 text = text.replace(ENV_PATTERN, (_, rawName: string) => {
108 const varName = rawName.trim();
109 const value = varName ? process.env[varName] : undefined;
110 if (value === undefined || value === "") {
111 warnings.push(
112 `Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`,
113 );
114 return "";
115 }
116
117 return JSON.stringify(value).slice(1, -1);
118 });
119
120 const fileMatches = Array.from(text.matchAll(FILE_PATTERN));
121 if (fileMatches.length === 0) {
122 return { text, warnings };
123 }
124
125 const configDir = input.configPath ? dirname(input.configPath) : process.cwd();
126
127 let output = "";
128 let cursor = 0;
129
130 for (const match of fileMatches) {
131 const token = match[0];
132 const rawPath = match[1] ?? "";
133 const index = match.index ?? 0;
134
135 output += text.slice(cursor, index);
136 cursor = index + token.length;

Callers 6

loadConfigFileDetailedFunction · 0.90
variable.test.tsFile · 0.90
readConfigForEmbeddingFunction · 0.90
checkEmbeddingConfigFunction · 0.90
runDoctorFunction · 0.90
loadConfigFileFunction · 0.90

Calls 3

stripJsonCommentsFunction · 0.90
sensitiveFilePathReasonFunction · 0.85
resolveFunction · 0.50

Tested by

no test coverage detected