@nanocollective/nanocoder 1.13.2 → 1.13.3
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/README.md +16 -0
- package/dist/config/env-substitution.d.ts +4 -0
- package/dist/config/env-substitution.d.ts.map +1 -0
- package/dist/config/env-substitution.js +51 -0
- package/dist/config/env-substitution.js.map +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +11 -4
- package/dist/config/index.js.map +1 -1
- package/dist/types/core.js +1 -1
- package/dist/types/core.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -164,6 +164,15 @@ Nanocoder supports any OpenAI-compatible API through a unified provider configur
|
|
|
164
164
|
- `apiKey`: API key (optional, may not be required)
|
|
165
165
|
- `models`: Available model list for `/model` command
|
|
166
166
|
|
|
167
|
+
**Environment Variables:**
|
|
168
|
+
|
|
169
|
+
Keep API keys out of version control using environment variables. Variables are loaded from shell environment (`.bashrc`, `.zshrc`) or `.env` file in your working directory.
|
|
170
|
+
|
|
171
|
+
**Syntax:** `$VAR_NAME`, `${VAR_NAME}`, or `${VAR_NAME:-default}`
|
|
172
|
+
**Supported in:** `baseUrl`, `apiKey`, `models`, MCP server `command`, `args`, `env`
|
|
173
|
+
|
|
174
|
+
See `.env.example` for setup instructions
|
|
175
|
+
|
|
167
176
|
**Timeout Configuration:**
|
|
168
177
|
|
|
169
178
|
Nanocoder allows you to configure timeouts for your AI providers to handle long-running requests.
|
|
@@ -236,6 +245,13 @@ Nanocoder supports connecting to MCP servers to extend its capabilities with add
|
|
|
236
245
|
}
|
|
237
246
|
```
|
|
238
247
|
|
|
248
|
+
**MCP Server Configuration:**
|
|
249
|
+
|
|
250
|
+
- `name`: Display name for the MCP server
|
|
251
|
+
- `command`: Executable command to start the server
|
|
252
|
+
- `args`: Array of command-line arguments
|
|
253
|
+
- `env`: Environment variables for the server process
|
|
254
|
+
|
|
239
255
|
When MCP servers are configured, Nanocoder will:
|
|
240
256
|
|
|
241
257
|
- Automatically connect to all configured servers on startup
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-substitution.d.ts","sourceRoot":"","sources":["../../source/config/env-substitution.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAMtD;AAGD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA8BhD;AAGD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAuBjD"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { shouldLog } from './logging.js';
|
|
2
|
+
import { logError } from '../utils/message-queue.js';
|
|
3
|
+
// Check if a string contains environment variable references
|
|
4
|
+
export function isEnvVarReference(str) {
|
|
5
|
+
if (typeof str !== 'string') {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
return /\$\{[A-Z_][A-Z0-9_]*(?::-[^}]*)?\}|\$[A-Z_][A-Z0-9_]*/g.test(str);
|
|
9
|
+
}
|
|
10
|
+
// Expand environment variable references in a string
|
|
11
|
+
export function expandEnvVar(str) {
|
|
12
|
+
if (typeof str !== 'string') {
|
|
13
|
+
return str;
|
|
14
|
+
}
|
|
15
|
+
const regex = /\$\{([A-Z_][A-Z0-9_]*)(?::-(.*?))?\}|\$([A-Z_][A-Z0-9_]*)/g;
|
|
16
|
+
return str.replace(regex, (match, bracedVarName, defaultValue, unbracedVarName) => {
|
|
17
|
+
const varName = bracedVarName || unbracedVarName;
|
|
18
|
+
const envValue = process.env[varName];
|
|
19
|
+
if (envValue !== undefined) {
|
|
20
|
+
return envValue;
|
|
21
|
+
}
|
|
22
|
+
if (defaultValue !== undefined) {
|
|
23
|
+
return defaultValue;
|
|
24
|
+
}
|
|
25
|
+
if (shouldLog('warn')) {
|
|
26
|
+
logError(`Environment variable ${varName} not found in config, using empty string`);
|
|
27
|
+
}
|
|
28
|
+
return '';
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// Recursively substitute environment variables in objects, arrays, and strings
|
|
32
|
+
export function substituteEnvVars(value) {
|
|
33
|
+
if (value === null || value === undefined) {
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
if (typeof value === 'string') {
|
|
37
|
+
return expandEnvVar(value);
|
|
38
|
+
}
|
|
39
|
+
if (Array.isArray(value)) {
|
|
40
|
+
return value.map(item => substituteEnvVars(item));
|
|
41
|
+
}
|
|
42
|
+
if (typeof value === 'object') {
|
|
43
|
+
const result = {};
|
|
44
|
+
for (const [key, val] of Object.entries(value)) {
|
|
45
|
+
result[key] = substituteEnvVars(val);
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=env-substitution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-substitution.js","sourceRoot":"","sources":["../../source/config/env-substitution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AAEnD,6DAA6D;AAC7D,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,wDAAwD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3E,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,YAAY,CAAC,GAAW;IACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAG,4DAA4D,CAAC;IAE3E,OAAO,GAAG,CAAC,OAAO,CACjB,KAAK,EACL,CAAC,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE;QACvD,MAAM,OAAO,GAAG,aAAa,IAAI,eAAe,CAAC;QACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,QAAQ,CAAC;QACjB,CAAC;QAED,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,YAAY,CAAC;QACrB,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,QAAQ,CACP,wBAAwB,OAAO,0CAA0C,CACzE,CAAC;QACH,CAAC;QAED,OAAO,EAAE,CAAC;IACX,CAAC,CACD,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAAC,KAAU;IAC3C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACd,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAuCzD,eAAO,MAAM,SAAS,WAAkB,CAAC;AAGzC,eAAO,MAAM,YAAY;;;CAGxB,CAAC;AAEF,wBAAgB,SAAS,IAAI,MAAM,CAIlC;AAGD,eAAO,MAAM,MAAM,EAAE,MAAoB,CAAC;AAM1C,eAAO,MAAM,UAAU,QAGtB,CAAC"}
|
package/dist/config/index.js
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'fs';
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import { config as loadEnv } from 'dotenv';
|
|
4
5
|
import { logError } from '../utils/message-queue.js';
|
|
5
6
|
import { loadPreferences } from './preferences.js';
|
|
6
7
|
import { getThemeColors, defaultTheme } from './themes.js';
|
|
8
|
+
import { substituteEnvVars } from './env-substitution.js';
|
|
9
|
+
// Load .env file from working directory (shell environment takes precedence)
|
|
10
|
+
loadEnv({ path: join(process.cwd(), '.env') });
|
|
7
11
|
// Function to load app configuration from agents.config.json if it exists
|
|
8
12
|
function loadAppConfig() {
|
|
9
13
|
const agentsJsonPath = join(process.cwd(), 'agents.config.json');
|
|
10
14
|
if (existsSync(agentsJsonPath)) {
|
|
11
15
|
try {
|
|
12
|
-
const
|
|
13
|
-
|
|
16
|
+
const rawData = readFileSync(agentsJsonPath, 'utf-8');
|
|
17
|
+
const agentsData = JSON.parse(rawData);
|
|
18
|
+
// Apply environment variable substitution
|
|
19
|
+
const processedData = substituteEnvVars(agentsData);
|
|
20
|
+
if (processedData.nanocoder) {
|
|
14
21
|
return {
|
|
15
|
-
providers:
|
|
16
|
-
mcpServers:
|
|
22
|
+
providers: processedData.nanocoder.providers,
|
|
23
|
+
mcpServers: processedData.nanocoder.mcpServers,
|
|
17
24
|
};
|
|
18
25
|
}
|
|
19
26
|
}
|
package/dist/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/config/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,UAAU,EAAE,YAAY,EAAC,MAAM,IAAI,CAAC;AAC5C,OAAO,EAAC,IAAI,EAAE,OAAO,EAAC,MAAM,MAAM,CAAC;AACnC,OAAO,EAAC,aAAa,EAAC,MAAM,KAAK,CAAC;AAClC,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/config/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,UAAU,EAAE,YAAY,EAAC,MAAM,IAAI,CAAC;AAC5C,OAAO,EAAC,IAAI,EAAE,OAAO,EAAC,MAAM,MAAM,CAAC;AACnC,OAAO,EAAC,aAAa,EAAC,MAAM,KAAK,CAAC;AAClC,OAAO,EAAC,MAAM,IAAI,OAAO,EAAC,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,aAAa,CAAC;AACzD,OAAO,EAAC,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AAExD,6EAA6E;AAC7E,OAAO,CAAC,EAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAC,CAAC,CAAC;AAE7C,0EAA0E;AAC1E,SAAS,aAAa;IACrB,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAEjE,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAEvC,0CAA0C;YAC1C,MAAM,aAAa,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAEpD,IAAI,aAAa,CAAC,SAAS,EAAE,CAAC;gBAC7B,OAAO;oBACN,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC,SAAS;oBAC5C,UAAU,EAAE,aAAa,CAAC,SAAS,CAAC,UAAU;iBAC9C,CAAC;YACH,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,QAAQ,CAAC,uCAAuC,KAAK,EAAE,CAAC,CAAC;QAC1D,CAAC;IACF,CAAC;IAED,OAAO,EAAE,CAAC;AACX,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;AAEzC,iFAAiF;AACjF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;CACjB,CAAC;AAEF,MAAM,UAAU,SAAS;IACxB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,aAAa,GAAG,WAAW,CAAC,aAAa,IAAI,YAAY,CAAC;IAChE,OAAO,cAAc,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,MAAM,GAAW,SAAS,EAAE,CAAC;AAE1C,kEAAkE;AAClE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,oFAAoF;AACpF,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAC7B,SAAS,EACT,yCAAyC,CACzC,CAAC"}
|
package/dist/types/core.js
CHANGED
package/dist/types/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../source/types/core.ts"],"names":[],"mappings":"AA0EA,MAAM,CAAC,MAAM,uBAAuB,GAAoC;IACvE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../source/types/core.ts"],"names":[],"mappings":"AA0EA,MAAM,CAAC,MAAM,uBAAuB,GAAoC;IACvE,MAAM,EAAE,kBAAkB;IAC1B,aAAa,EAAE,wBAAwB;IACvC,IAAI,EAAE,gBAAgB;CACtB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanocollective/nanocoder",
|
|
3
3
|
"main": "dist/cli.js",
|
|
4
|
-
"version": "1.13.
|
|
4
|
+
"version": "1.13.3",
|
|
5
5
|
"description": "A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"cli",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"@nanostores/react": "^1.0.0",
|
|
51
51
|
"cheerio": "^1.1.2",
|
|
52
52
|
"cli-highlight": "^2.1.11",
|
|
53
|
+
"dotenv": "^17.2.3",
|
|
53
54
|
"ink": "^6.3.1",
|
|
54
55
|
"ink-big-text": "^2.0.0",
|
|
55
56
|
"ink-gradient": "^3.0.0",
|