Skip to content

Commit 9a406f7

Browse files
authored
Merge pull request #6476 from elizaOS/odi-bs-opt
feat(plugin-bootstrap): comprehensive optimization and robustness imp…
2 parents 8cbf06f + cef942e commit 9a406f7

20 files changed

Lines changed: 1974 additions & 678 deletions

bun.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/**
2+
* Beautiful plugin settings banner with custom ASCII art
3+
* Bootstrap Plugin - The foundation of every elizaOS agent
4+
*/
5+
6+
import type { IAgentRuntime } from '@elizaos/core';
7+
8+
// Bootstrap: Teal/Startup theme - unique palette
9+
const ANSI = {
10+
reset: '\x1b[0m',
11+
bold: '\x1b[1m',
12+
dim: '\x1b[2m',
13+
teal: '\x1b[31m',
14+
tealBright: '\x1b[37m',
15+
mint: '\x1b[37m',
16+
brightGreen: '\x1b[92m',
17+
brightYellow: '\x1b[93m',
18+
brightMagenta: '\x1b[95m',
19+
brightWhite: '\x1b[97m',
20+
brightRed: '\x1b[91m',
21+
brightBlue: '\x1b[94m',
22+
};
23+
24+
export interface PluginSetting {
25+
name: string;
26+
value: unknown;
27+
defaultValue?: unknown;
28+
sensitive?: boolean;
29+
required?: boolean;
30+
}
31+
32+
export interface BannerOptions {
33+
runtime: IAgentRuntime;
34+
settings?: PluginSetting[];
35+
}
36+
37+
function mask(v: string): string {
38+
if (!v || v.length < 8) return '••••••••';
39+
return `${v.slice(0, 4)}${'•'.repeat(Math.min(12, v.length - 8))}${v.slice(-4)}`;
40+
}
41+
42+
function fmtVal(value: unknown, sensitive: boolean, maxLen: number): string {
43+
let s: string;
44+
if (value === undefined || value === null || value === '') {
45+
s = '(not set)';
46+
} else if (sensitive) {
47+
s = mask(String(value));
48+
} else {
49+
s = String(value);
50+
}
51+
if (s.length > maxLen) s = s.slice(0, maxLen - 3) + '...';
52+
return s;
53+
}
54+
55+
function isDef(v: unknown, d: unknown): boolean {
56+
if (v === undefined || v === null || v === '') return true;
57+
return d !== undefined && v === d;
58+
}
59+
60+
function pad(s: string, n: number): string {
61+
const len = s.replace(/\x1b\[[0-9;]*m/g, '').length;
62+
if (len >= n) return s;
63+
return s + ' '.repeat(n - len);
64+
}
65+
66+
function line(content: string): string {
67+
const stripped = content.replace(/\x1b\[[0-9;]*m/g, '');
68+
const len = stripped.length;
69+
if (len > 78) return content.slice(0, 78);
70+
return content + ' '.repeat(78 - len);
71+
}
72+
73+
export function printBanner(options: BannerOptions): void {
74+
const { settings = [], runtime } = options;
75+
const R = ANSI.reset, D = ANSI.dim, B = ANSI.bold;
76+
const C = ANSI.teal, c2 = ANSI.tealBright, M = ANSI.mint;
77+
const G = ANSI.brightGreen, Y = ANSI.brightYellow;
78+
79+
const top = `${C}${'═'.repeat(78)}${R}`;
80+
const mid = `${C}${'═'.repeat(78)}${R}`;
81+
const bot = `${C}${'═'.repeat(78)}${R}`;
82+
const row = (s: string) => `${C}${R}${line(s)}${C}${R}`;
83+
84+
const lines: string[] = [''];
85+
lines.push(top);
86+
lines.push(row(` ${B}Character: ${runtime.character.name}${R}`));
87+
lines.push(mid);
88+
89+
// Bootstrap - 3D Isometric Shadow Font with pyramid icon
90+
lines.push(row(`${c2} ____ __ __ ${M}${R}`));
91+
lines.push(row(`${c2} / __ ) ____ ____ ____/ /_ _____ / /_ _____ ____ _ ____ ${M} /▲\\${R}`));
92+
lines.push(row(`${c2} / __ |/ __ \\ / __ \\/ __ __// ___/ / __// ___// __ '// __ \\${M} / ▲ \\${R}`));
93+
lines.push(row(`${c2} / /_/ // /_/ // /_/ / /_/ /_ (__ ) / /_ / / / /_/ // /_/ /${M} / ▲ \\${R}`));
94+
lines.push(row(`${c2}/_____/ \\____/ \\____/\\__,___//____/ \\__//_/ \\__,_// .___/ ${M}/___▲___\\${R}`));
95+
lines.push(row(`${D} ${c2}/_/${R}`));
96+
lines.push(row(``));
97+
lines.push(row(`${M} Agent Foundation • Actions • Evaluators • Providers${R}`));
98+
lines.push(mid);
99+
100+
if (settings.length > 0) {
101+
const NW = 32, VW = 28, SW = 8;
102+
lines.push(row(` ${B}${pad('ENV VARIABLE', NW)} ${pad('VALUE', VW)} ${pad('STATUS', SW)}${R}`));
103+
lines.push(row(` ${D}${'-'.repeat(NW)} ${'-'.repeat(VW)} ${'-'.repeat(SW)}${R}`));
104+
105+
for (const s of settings) {
106+
const def = isDef(s.value, s.defaultValue);
107+
const set = s.value !== undefined && s.value !== null && s.value !== '';
108+
109+
let ico: string, st: string;
110+
if (!set && s.required) {
111+
ico = `${ANSI.brightRed}${R}`;
112+
st = `${ANSI.brightRed}REQUIRED${R}`;
113+
} else if (!set) {
114+
ico = `${D}${R}`;
115+
st = `${D}default${R}`;
116+
} else if (def) {
117+
ico = `${ANSI.brightBlue}${R}`;
118+
st = `${ANSI.brightBlue}default${R}`;
119+
} else {
120+
ico = `${G}${R}`;
121+
st = `${G}custom${R}`;
122+
}
123+
124+
const name = pad(s.name, NW - 2);
125+
const val = pad(fmtVal(s.value ?? s.defaultValue, s.sensitive ?? false, VW), VW);
126+
const status = pad(st, SW);
127+
lines.push(row(` ${ico} ${c2}${name}${R} ${val} ${status}`));
128+
}
129+
130+
lines.push(mid);
131+
lines.push(row(` ${D}${G}${D} custom ${ANSI.brightBlue}${D} default ○ unset ${ANSI.brightRed}${D} required → Set in .env${R}`));
132+
} else {
133+
lines.push(row(` ${G}${R} ${Y}Actions${R} reply, sendMessage, followRoom, muteRoom, generateImage...`));
134+
lines.push(row(` ${G}${R} ${Y}Evaluators${R} reflection, memory consolidation, learning`));
135+
lines.push(row(` ${G}${R} ${Y}Providers${R} time, entities, facts, relationships, attachments...`));
136+
lines.push(row(` ${G}${R} ${Y}Services${R} TaskService, EmbeddingGenerationService`));
137+
lines.push(mid);
138+
lines.push(row(` ${D}The foundation that gives every elizaOS agent its core capabilities${R}`));
139+
}
140+
141+
lines.push(bot);
142+
lines.push('');
143+
144+
runtime.logger.info(lines.join('\n'));
145+
}

0 commit comments

Comments
 (0)