Skip to content

Commit

Permalink
Merge pull request #1454 from odilitime/dev
Browse files Browse the repository at this point in the history
feat: allow passing secrets through environment
  • Loading branch information
odilitime authored Dec 26, 2024
2 parents 5acaaf8 + 089cb33 commit 99f4eca
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 4 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ packages/core/src/providers/cache
packages/core/src/providers/cache/*
cache/*
packages/plugin-coinbase/src/plugins/transactions.csv
packages/plugin-coinbase/package-lock.json

tsup.config.bundled_*.mjs

Expand Down
19 changes: 19 additions & 0 deletions agent/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,25 @@ export async function loadCharacters(
const character = JSON.parse(content);
validateCharacterConfig(character);

// .id isn't really valid
const characterId = character.id || character.name;
const characterPrefix = `CHARACTER.${characterId.toUpperCase().replace(/ /g, '_')}.`;

const characterSettings = Object.entries(process.env)
.filter(([key]) => key.startsWith(characterPrefix))
.reduce((settings, [key, value]) => {
const settingKey = key.slice(characterPrefix.length);
return { ...settings, [settingKey]: value };
}, {});

if (Object.keys(characterSettings).length > 0) {
character.settings = character.settings || {};
character.settings.secrets = {
...characterSettings,
...character.settings.secrets
};
}

// Handle plugins
if (isAllStrings(character.plugins)) {
elizaLogger.info("Plugins are: ", character.plugins);
Expand Down
9 changes: 6 additions & 3 deletions docs/docs/guides/secrets-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ A comprehensive guide for managing secrets, API keys, and sensitive configuratio

Eliza uses a hierarchical environment variable system:

1. Character-specific secrets (highest priority)
2. Environment variables
3. Default values (lowest priority)
1. Character-specific namespaced environment variables (highest priority)
2. Character-specific secrets
3. Environment variables
4. Default values (lowest priority)

### Secret Types

Expand Down Expand Up @@ -96,6 +97,8 @@ Define secrets in character files:
}
```

Alternatively, you can use the `CHARACTER.YOUR_CHARACTER_NAME.SECRET_NAME` format inside your `.env` file.

Access secrets in code:

```typescript
Expand Down
14 changes: 14 additions & 0 deletions docs/docs/packages/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ export async function initializeClients(

### Token Management

Tokens can be configured in two ways:

1. Using namespaced environment variables:
```env
CHARACTER.YOUR_CHARACTER_NAME.OPENAI_API_KEY=sk-...
CHARACTER.YOUR_CHARACTER_NAME.ANTHROPIC_API_KEY=sk-...
```

2. Using character settings:
```typescript
export function getTokenForProvider(
provider: ModelProviderName,
Expand All @@ -181,6 +190,11 @@ export function getTokenForProvider(
}
```

The system will check for tokens in the following order:
1. Character-specific namespaced env variables
2. Character settings from JSON
3. Global environment variables

### Database Selection

```typescript
Expand Down
31 changes: 31 additions & 0 deletions packages/core/src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ interface Settings {
[key: string]: string | undefined;
}

interface NamespacedSettings {
[namespace: string]: Settings;
}

let environmentSettings: Settings = {};

/**
Expand Down Expand Up @@ -91,6 +95,15 @@ export function loadEnvConfig(): Settings {
if (!result.error) {
console.log(`Loaded .env file from: ${envPath}`);
}

// Parse namespaced settings
const namespacedSettings = parseNamespacedSettings(process.env as Settings);

// Attach to process.env for backward compatibility
Object.entries(namespacedSettings).forEach(([namespace, settings]) => {
process.env[`__namespaced_${namespace}`] = JSON.stringify(settings);
});

return process.env as Settings;
}

Expand Down Expand Up @@ -135,3 +148,21 @@ elizaLogger.info("Parsed settings:", {
});

export default settings;

// Add this function to parse namespaced settings
function parseNamespacedSettings(env: Settings): NamespacedSettings {
const namespaced: NamespacedSettings = {};

for (const [key, value] of Object.entries(env)) {
if (!value) continue;

const [namespace, ...rest] = key.split('.');
if (!namespace || rest.length === 0) continue;

const settingKey = rest.join('.');
namespaced[namespace] = namespaced[namespace] || {};
namespaced[namespace][settingKey] = value;
}

return namespaced;
}

0 comments on commit 99f4eca

Please sign in to comment.