codebot-ai 2.0.2 → 2.1.1
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/banner.d.ts +38 -5
- package/dist/banner.js +262 -80
- package/dist/cli.js +17 -4
- package/dist/encryption.d.ts +67 -0
- package/dist/encryption.js +209 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +29 -2
- package/dist/metrics.d.ts +35 -1
- package/dist/metrics.js +130 -2
- package/dist/policy.d.ts +26 -0
- package/dist/policy.js +85 -4
- package/package.json +14 -4
package/dist/banner.d.ts
CHANGED
|
@@ -2,18 +2,51 @@
|
|
|
2
2
|
* CodeBot AI mascot and CLI banner.
|
|
3
3
|
*
|
|
4
4
|
* Mascot name: Codi
|
|
5
|
-
* Three designs:
|
|
5
|
+
* Three designs: Neural Core, Terminal Shield, Sentinel
|
|
6
|
+
* See BRANDING.md for full identity guide.
|
|
7
|
+
*
|
|
8
|
+
* Design philosophy: Enterprise-grade. Clean geometry.
|
|
9
|
+
* No crayon vibes — precision engineering.
|
|
6
10
|
*/
|
|
7
|
-
export
|
|
11
|
+
export type CodiMood = 'ready' | 'working' | 'success' | 'error' | 'thinking' | 'idle' | 'alert';
|
|
12
|
+
export declare const MASCOT_1 = "\n \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 \u250C\u2500\u2500\u2510 \u250C\u2500\u2500\u2510 \u2502\n \u2502 \u2502\u2593\u2593\u2502 \u2502\u2593\u2593\u2502 \u2502\n \u2502 \u2514\u2500\u2500\u2518 \u2514\u2500\u2500\u2518 \u2502\n \u2576\u2500\u2500\u2500\u2500\u2524 \u251C\u2500\u2500\u2500\u2500\u2574\n \u2502 \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F \u2502\n \u2502 \u2502\n \u2514\u2500\u2500\u252C\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u252C\u2500\u2500\u2518\n \u2502 \u2502 \u2502 \u2502\n";
|
|
8
13
|
export declare const BANNER_1: (version: string, model: string, provider: string, session: string, autonomous: boolean) => string;
|
|
9
|
-
export declare const MASCOT_2 = "\n \
|
|
14
|
+
export declare const MASCOT_2 = "\n \u250C\u2500\u2510 \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557 \u250C\u2500\u2510\n \u2502\u2591\u2502 \u2551 \u25C9 \u25C9 \u2551 \u2502\u2591\u2502\n \u2502\u2591\u2502 \u2551 \u2551 \u2502\u2591\u2502\n \u2502\u2591\u2502 \u2551 \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F \u2551 \u2502\u2591\u2502\n \u2502\u2591\u2502 \u2551 \u2551 \u2502\u2591\u2502\n \u2514\u2500\u2518 \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u2514\u2500\u2518\n \u25AA \u25AA \u25AA \u25AA \u25AA \u25AA \u25AA \u25AA\n";
|
|
10
15
|
export declare const BANNER_2: (version: string, model: string, provider: string, session: string, autonomous: boolean) => string;
|
|
11
|
-
export declare const MASCOT_3 = "\n
|
|
16
|
+
export declare const MASCOT_3 = "\n \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n \u2554\u255D \u255A\u2557\n \u2551 \u2591\u2591\u2591\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591 \u2551\n \u2551 \u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591 \u2551\n \u255A\u2557 \u2554\u255D\n \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n \u2551 \u2551 \u2551 \u2551\n";
|
|
12
17
|
export declare const BANNER_3: (version: string, model: string, provider: string, session: string, autonomous: boolean) => string;
|
|
13
18
|
export declare const banner: (version: string, model: string, provider: string, session: string, autonomous: boolean) => string;
|
|
14
|
-
export declare
|
|
19
|
+
export declare const CODI_FACE: Record<CodiMood, string>;
|
|
20
|
+
/**
|
|
21
|
+
* Random startup greeting from Codi.
|
|
22
|
+
*/
|
|
23
|
+
export declare function randomGreeting(mood?: string): string;
|
|
24
|
+
export interface CodiReaction {
|
|
25
|
+
face: string;
|
|
26
|
+
message: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get a context-aware reaction from Codi.
|
|
30
|
+
* Returns a face expression + message pair.
|
|
31
|
+
*/
|
|
32
|
+
export declare function codiReact(event: string): CodiReaction;
|
|
33
|
+
/**
|
|
34
|
+
* Format a Codi reaction as a styled CLI string.
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatReaction(event: string): string;
|
|
37
|
+
export declare function sessionSummaryBanner(stats: {
|
|
38
|
+
iterations: number;
|
|
39
|
+
toolCalls: number;
|
|
40
|
+
tokensUsed: number;
|
|
41
|
+
cost?: number;
|
|
42
|
+
duration?: number;
|
|
43
|
+
}): string;
|
|
15
44
|
/**
|
|
16
45
|
* Compact single-line startup for non-TTY / piped usage.
|
|
17
46
|
*/
|
|
18
47
|
export declare function compactBanner(version: string, model: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Pick a random banner design (for variety on startup).
|
|
50
|
+
*/
|
|
51
|
+
export declare function randomBanner(): typeof BANNER_1;
|
|
19
52
|
//# sourceMappingURL=banner.d.ts.map
|
package/dist/banner.js
CHANGED
|
@@ -3,12 +3,20 @@
|
|
|
3
3
|
* CodeBot AI mascot and CLI banner.
|
|
4
4
|
*
|
|
5
5
|
* Mascot name: Codi
|
|
6
|
-
* Three designs:
|
|
6
|
+
* Three designs: Neural Core, Terminal Shield, Sentinel
|
|
7
|
+
* See BRANDING.md for full identity guide.
|
|
8
|
+
*
|
|
9
|
+
* Design philosophy: Enterprise-grade. Clean geometry.
|
|
10
|
+
* No crayon vibes — precision engineering.
|
|
7
11
|
*/
|
|
8
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.banner = exports.BANNER_3 = exports.MASCOT_3 = exports.BANNER_2 = exports.MASCOT_2 = exports.BANNER_1 = exports.MASCOT_1 = void 0;
|
|
13
|
+
exports.CODI_FACE = exports.banner = exports.BANNER_3 = exports.MASCOT_3 = exports.BANNER_2 = exports.MASCOT_2 = exports.BANNER_1 = exports.MASCOT_1 = void 0;
|
|
10
14
|
exports.randomGreeting = randomGreeting;
|
|
15
|
+
exports.codiReact = codiReact;
|
|
16
|
+
exports.formatReaction = formatReaction;
|
|
17
|
+
exports.sessionSummaryBanner = sessionSummaryBanner;
|
|
11
18
|
exports.compactBanner = compactBanner;
|
|
19
|
+
exports.randomBanner = randomBanner;
|
|
12
20
|
const C = {
|
|
13
21
|
reset: '\x1b[0m',
|
|
14
22
|
bold: '\x1b[1m',
|
|
@@ -25,119 +33,286 @@ const C = {
|
|
|
25
33
|
brightYellow: '\x1b[93m',
|
|
26
34
|
brightMagenta: '\x1b[95m',
|
|
27
35
|
brightWhite: '\x1b[97m',
|
|
36
|
+
brightRed: '\x1b[91m',
|
|
37
|
+
brightBlue: '\x1b[94m',
|
|
28
38
|
};
|
|
29
|
-
//
|
|
30
|
-
// DESIGN 1: "
|
|
31
|
-
//
|
|
32
|
-
//
|
|
39
|
+
// ─────────────────────────────────────────────────────────────
|
|
40
|
+
// DESIGN 1: "Neural Core" — Precision-engineered AI processor
|
|
41
|
+
// Clean, symmetric, enterprise. The signature look.
|
|
42
|
+
// ─────────────────────────────────────────────────────────────
|
|
33
43
|
exports.MASCOT_1 = `
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
┌─────────────────────┐
|
|
45
|
+
│ ┌──┐ ┌──┐ │
|
|
46
|
+
│ │▓▓│ │▓▓│ │
|
|
47
|
+
│ └──┘ └──┘ │
|
|
48
|
+
╶────┤ ├────╴
|
|
49
|
+
│ ╰─────────╯ │
|
|
50
|
+
│ │
|
|
51
|
+
└──┬──┬───────┬──┬──┘
|
|
52
|
+
│ │ │ │
|
|
42
53
|
`;
|
|
43
54
|
const BANNER_1 = (version, model, provider, session, autonomous) => {
|
|
55
|
+
const a = C.cyan; // frame
|
|
56
|
+
const e = C.brightGreen; // eyes
|
|
57
|
+
const m = C.brightCyan; // mouth
|
|
58
|
+
const d = C.dim; // connectors
|
|
59
|
+
const r = C.reset;
|
|
44
60
|
const lines = [
|
|
45
61
|
'',
|
|
46
|
-
`${
|
|
47
|
-
`${
|
|
48
|
-
`${
|
|
49
|
-
`${
|
|
50
|
-
`${
|
|
51
|
-
`${
|
|
52
|
-
`${
|
|
53
|
-
`${
|
|
54
|
-
autonomous ? `
|
|
62
|
+
`${a} ┌─────────────────────┐${r}`,
|
|
63
|
+
`${a} │${r} ${e}┌──┐${r} ${e}┌──┐${r} ${a}│${r}`,
|
|
64
|
+
`${a} │${r} ${e}│▓▓│${r} ${e}│▓▓│${r} ${a}│${r} ${C.bold}${C.brightCyan}CodeBot AI${r} ${d}v${version}${r}`,
|
|
65
|
+
`${a} │${r} ${e}└──┘${r} ${e}└──┘${r} ${a}│${r} ${d}Think local. Code global.${r}`,
|
|
66
|
+
`${d} ╶────${a}┤${r} ${a}├${d}────╴${r}`,
|
|
67
|
+
`${a} │${r} ${m}╰─────────╯${r} ${a}│${r} ${d}Model: ${C.white}${model}${r}`,
|
|
68
|
+
`${a} │${r} ${a}│${r} ${d}Provider: ${C.white}${provider}${r}`,
|
|
69
|
+
`${a} └──┬──┬───────┬──┬──┘${r} ${d}Session: ${C.white}${session}${r}`,
|
|
70
|
+
`${d} │ │ │ │${r}` + (autonomous ? ` ${C.brightYellow}${C.bold}⚡ AUTONOMOUS${r}` : ''),
|
|
55
71
|
'',
|
|
56
72
|
];
|
|
57
73
|
return lines.join('\n');
|
|
58
74
|
};
|
|
59
75
|
exports.BANNER_1 = BANNER_1;
|
|
60
|
-
//
|
|
61
|
-
// DESIGN 2: "
|
|
62
|
-
//
|
|
63
|
-
//
|
|
76
|
+
// ─────────────────────────────────────────────────────────────
|
|
77
|
+
// DESIGN 2: "Terminal Shield" — Secure terminal with status LEDs
|
|
78
|
+
// Enterprise security aesthetic. Trust indicator built in.
|
|
79
|
+
// ─────────────────────────────────────────────────────────────
|
|
64
80
|
exports.MASCOT_2 = `
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
┌─┐ ╔═══════════════════╗ ┌─┐
|
|
82
|
+
│░│ ║ ◉ ◉ ║ │░│
|
|
83
|
+
│░│ ║ ║ │░│
|
|
84
|
+
│░│ ║ ╰───────────╯ ║ │░│
|
|
85
|
+
│░│ ║ ║ │░│
|
|
86
|
+
└─┘ ╚═══════════════════╝ └─┘
|
|
87
|
+
▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪
|
|
72
88
|
`;
|
|
73
89
|
const BANNER_2 = (version, model, provider, session, autonomous) => {
|
|
90
|
+
const f = C.cyan; // frame
|
|
91
|
+
const s = C.dim; // side panels
|
|
92
|
+
const e = C.brightGreen; // eyes
|
|
93
|
+
const m = C.brightCyan; // mouth
|
|
94
|
+
const r = C.reset;
|
|
95
|
+
const led = C.brightGreen;
|
|
74
96
|
const lines = [
|
|
75
97
|
'',
|
|
76
|
-
`${
|
|
77
|
-
`${
|
|
78
|
-
`${
|
|
79
|
-
`${
|
|
80
|
-
`${
|
|
81
|
-
`${
|
|
82
|
-
|
|
83
|
-
`
|
|
84
|
-
autonomous ? ` ${C.brightYellow}${C.bold}⚡ AUTONOMOUS${C.reset}` : '',
|
|
98
|
+
`${s} ┌─┐${r} ${f}╔═══════════════════╗${r} ${s}┌─┐${r}`,
|
|
99
|
+
`${s} │░│${r} ${f}║${r} ${e}◉${r} ${e}◉${r} ${f}║${r} ${s}│░│${r} ${C.bold}${C.brightCyan}CodeBot AI${r} ${C.dim}v${version}${r}`,
|
|
100
|
+
`${s} │░│${r} ${f}║${r} ${f}║${r} ${s}│░│${r} ${C.dim}Think local. Code global.${r}`,
|
|
101
|
+
`${s} │░│${r} ${f}║${r} ${m}╰───────────╯${r} ${f}║${r} ${s}│░│${r}`,
|
|
102
|
+
`${s} │░│${r} ${f}║${r} ${f}║${r} ${s}│░│${r} ${C.dim}Model: ${C.white}${model}${r}`,
|
|
103
|
+
`${s} └─┘${r} ${f}╚═══════════════════╝${r} ${s}└─┘${r} ${C.dim}Provider: ${C.white}${provider}${r}`,
|
|
104
|
+
` ${led}▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪${r} ${C.dim}Session: ${C.white}${session}${r}`,
|
|
105
|
+
autonomous ? ` ${C.brightYellow}${C.bold}⚡ AUTONOMOUS${r}` : '',
|
|
85
106
|
'',
|
|
86
107
|
];
|
|
87
108
|
return lines.join('\n');
|
|
88
109
|
};
|
|
89
110
|
exports.BANNER_2 = BANNER_2;
|
|
90
|
-
//
|
|
91
|
-
// DESIGN 3: "
|
|
92
|
-
//
|
|
93
|
-
//
|
|
111
|
+
// ─────────────────────────────────────────────────────────────
|
|
112
|
+
// DESIGN 3: "Sentinel" — Armored visor. Threat detection mode.
|
|
113
|
+
// Cybersecurity aesthetic. Used in autonomous/scanning contexts.
|
|
114
|
+
// ─────────────────────────────────────────────────────────────
|
|
94
115
|
exports.MASCOT_3 = `
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
╔═══════════╗
|
|
117
|
+
╔╝ ╚╗
|
|
118
|
+
║ ░░░█████░░░ ║
|
|
119
|
+
║ ░░░░░░░░░░░ ║
|
|
120
|
+
╚╗ ╔╝
|
|
121
|
+
╚═══════════╝
|
|
122
|
+
║ ║ ║ ║
|
|
101
123
|
`;
|
|
102
124
|
const BANNER_3 = (version, model, provider, session, autonomous) => {
|
|
125
|
+
const f = C.cyan; // frame
|
|
126
|
+
const v = C.brightCyan; // visor glow
|
|
127
|
+
const g = C.brightGreen; // visor core
|
|
128
|
+
const d = C.dim;
|
|
129
|
+
const r = C.reset;
|
|
103
130
|
const lines = [
|
|
104
131
|
'',
|
|
105
|
-
`${
|
|
106
|
-
`${
|
|
107
|
-
`${
|
|
108
|
-
`${
|
|
109
|
-
`${
|
|
110
|
-
`${
|
|
111
|
-
|
|
112
|
-
autonomous ? `
|
|
132
|
+
`${f} ╔═══════════╗${r}`,
|
|
133
|
+
`${f} ╔╝${r} ${f}╚╗${r} ${C.bold}${C.brightCyan}CodeBot AI${r} ${d}v${version}${r}`,
|
|
134
|
+
`${f} ║${r} ${v}░░░${g}█████${v}░░░${r} ${f}║${r} ${d}Think local. Code global.${r}`,
|
|
135
|
+
`${f} ║${r} ${d}░░░░░░░░░░░${r} ${f}║${r}`,
|
|
136
|
+
`${f} ╚╗${r} ${f}╔╝${r} ${d}Model: ${C.white}${model}${r}`,
|
|
137
|
+
`${f} ╚═══════════╝${r} ${d}Provider: ${C.white}${provider}${r}`,
|
|
138
|
+
`${d} ║ ║ ║ ║${r} ${d}Session: ${C.white}${session}${r}`,
|
|
139
|
+
autonomous ? ` ${C.brightYellow}${C.bold}⚡ AUTONOMOUS${r}` : '',
|
|
113
140
|
'',
|
|
114
141
|
];
|
|
115
142
|
return lines.join('\n');
|
|
116
143
|
};
|
|
117
144
|
exports.BANNER_3 = BANNER_3;
|
|
118
|
-
//
|
|
119
|
-
// Default banner (Design 1 —
|
|
120
|
-
//
|
|
145
|
+
// ─────────────────────────────────────────────────────────────
|
|
146
|
+
// Default banner (Design 1 — Neural Core)
|
|
147
|
+
// ─────────────────────────────────────────────────────────────
|
|
121
148
|
exports.banner = exports.BANNER_1;
|
|
149
|
+
// ─────────────────────────────────────────────────────────────
|
|
150
|
+
// Codi's Expressions — Compact inline status indicators
|
|
151
|
+
// Enterprise-grade: no emoji, no cartoon. Clean symbols.
|
|
152
|
+
// ─────────────────────────────────────────────────────────────
|
|
153
|
+
exports.CODI_FACE = {
|
|
154
|
+
ready: `${C.cyan}[${C.brightGreen}◉ ◉${C.cyan}]${C.reset}`,
|
|
155
|
+
working: `${C.cyan}[${C.brightCyan}◎ ◎${C.cyan}]${C.reset}`,
|
|
156
|
+
success: `${C.cyan}[${C.brightGreen}● ●${C.cyan}]${C.reset}`,
|
|
157
|
+
error: `${C.cyan}[${C.brightRed}✕ ✕${C.cyan}]${C.reset}`,
|
|
158
|
+
thinking: `${C.cyan}[${C.brightYellow}◉ ${C.dim}·${C.cyan}]${C.reset}`,
|
|
159
|
+
idle: `${C.cyan}[${C.dim}· ·${C.cyan}]${C.reset}`,
|
|
160
|
+
alert: `${C.cyan}[${C.brightYellow}▲ ▲${C.cyan}]${C.reset}`,
|
|
161
|
+
};
|
|
162
|
+
// ─────────────────────────────────────────────────────────────
|
|
163
|
+
// Greeting System — Mood-categorized randomized greetings
|
|
164
|
+
// ─────────────────────────────────────────────────────────────
|
|
165
|
+
const GREETINGS_BY_MOOD = {
|
|
166
|
+
confident: [
|
|
167
|
+
"Systems online. Let's ship.",
|
|
168
|
+
"All circuits green. Ready to code.",
|
|
169
|
+
"No cloud. No limits. Let's go.",
|
|
170
|
+
"Standing by. Say the word.",
|
|
171
|
+
"Initialized. Awaiting instructions.",
|
|
172
|
+
"Signal locked. Ready to transmit.",
|
|
173
|
+
"Provider connected. Model hot. Let's go.",
|
|
174
|
+
],
|
|
175
|
+
playful: [
|
|
176
|
+
"What are we building today?",
|
|
177
|
+
"I read your codebase. We need to talk.",
|
|
178
|
+
"Your code, your machine, your move.",
|
|
179
|
+
"Another day, another deploy.",
|
|
180
|
+
"Booted up. Zero dependencies loaded.",
|
|
181
|
+
"Local power, global ambitions.",
|
|
182
|
+
"Scanned your repo. I have thoughts.",
|
|
183
|
+
],
|
|
184
|
+
security: [
|
|
185
|
+
"Eight security layers active. You're safe.",
|
|
186
|
+
"Hash chain intact. Trust verified.",
|
|
187
|
+
"Sandbox locked. Creativity unlocked.",
|
|
188
|
+
"Audit trail recording. Every move counts.",
|
|
189
|
+
"Policy loaded. Rules are rules.",
|
|
190
|
+
"Risk score: 0. Let's keep it that way.",
|
|
191
|
+
],
|
|
192
|
+
resuming: [
|
|
193
|
+
"Memory loaded. I remember everything.",
|
|
194
|
+
"Picking up where we left off.",
|
|
195
|
+
"Context restored. Continuity maintained.",
|
|
196
|
+
"Back online. Nothing lost.",
|
|
197
|
+
"Session recovered. Let's continue.",
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
/** All greetings flattened for random selection */
|
|
201
|
+
const ALL_GREETINGS = Object.values(GREETINGS_BY_MOOD).flat();
|
|
122
202
|
/**
|
|
123
203
|
* Random startup greeting from Codi.
|
|
124
204
|
*/
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
]
|
|
139
|
-
|
|
140
|
-
|
|
205
|
+
function randomGreeting(mood) {
|
|
206
|
+
const pool = mood && GREETINGS_BY_MOOD[mood]
|
|
207
|
+
? GREETINGS_BY_MOOD[mood]
|
|
208
|
+
: ALL_GREETINGS;
|
|
209
|
+
return pool[Math.floor(Math.random() * pool.length)];
|
|
210
|
+
}
|
|
211
|
+
const REACTIONS = {
|
|
212
|
+
tool_success: [
|
|
213
|
+
"Done.",
|
|
214
|
+
"Clean.",
|
|
215
|
+
"Handled.",
|
|
216
|
+
"Next?",
|
|
217
|
+
"Complete.",
|
|
218
|
+
],
|
|
219
|
+
tool_error: [
|
|
220
|
+
"That broke. Fixing.",
|
|
221
|
+
"Error caught. Adjusting.",
|
|
222
|
+
"Not ideal. Recovering.",
|
|
223
|
+
"Blocked. Finding another way.",
|
|
224
|
+
"Retrying with different approach.",
|
|
225
|
+
],
|
|
226
|
+
security_block: [
|
|
227
|
+
"Blocked. Policy violation.",
|
|
228
|
+
"Access denied. Security boundary hit.",
|
|
229
|
+
"Risk threshold exceeded. Skipping.",
|
|
230
|
+
"Denied. Policy enforced.",
|
|
231
|
+
"Path restricted. Cannot proceed.",
|
|
232
|
+
],
|
|
233
|
+
session_end: [
|
|
234
|
+
"Session complete. Audit trail sealed.",
|
|
235
|
+
"Signing off. All changes persisted.",
|
|
236
|
+
"Done. Metrics saved.",
|
|
237
|
+
"Session closed. Everything committed.",
|
|
238
|
+
"Shutting down cleanly.",
|
|
239
|
+
],
|
|
240
|
+
thinking: [
|
|
241
|
+
"Analyzing...",
|
|
242
|
+
"Processing...",
|
|
243
|
+
"Evaluating options...",
|
|
244
|
+
"Computing...",
|
|
245
|
+
"Working through it...",
|
|
246
|
+
],
|
|
247
|
+
cost_warning: [
|
|
248
|
+
"Token usage elevated.",
|
|
249
|
+
"Cost accumulating. Monitor budget.",
|
|
250
|
+
"High token throughput detected.",
|
|
251
|
+
"Budget advisory: cost climbing.",
|
|
252
|
+
],
|
|
253
|
+
autonomous_start: [
|
|
254
|
+
"Autonomous mode engaged.",
|
|
255
|
+
"Full automation active. No prompts.",
|
|
256
|
+
"Auto-pilot initialized.",
|
|
257
|
+
"Running unattended. All tools approved.",
|
|
258
|
+
"Autonomous. Maximum throughput.",
|
|
259
|
+
],
|
|
260
|
+
};
|
|
261
|
+
/**
|
|
262
|
+
* Get a context-aware reaction from Codi.
|
|
263
|
+
* Returns a face expression + message pair.
|
|
264
|
+
*/
|
|
265
|
+
function codiReact(event) {
|
|
266
|
+
let mood = 'ready';
|
|
267
|
+
if (event === 'tool_success' || event === 'session_end')
|
|
268
|
+
mood = 'success';
|
|
269
|
+
else if (event === 'tool_error')
|
|
270
|
+
mood = 'error';
|
|
271
|
+
else if (event === 'security_block')
|
|
272
|
+
mood = 'alert';
|
|
273
|
+
else if (event === 'thinking')
|
|
274
|
+
mood = 'thinking';
|
|
275
|
+
else if (event === 'cost_warning')
|
|
276
|
+
mood = 'alert';
|
|
277
|
+
else if (event === 'autonomous_start')
|
|
278
|
+
mood = 'working';
|
|
279
|
+
const messages = REACTIONS[event] || REACTIONS.tool_success;
|
|
280
|
+
const message = messages[Math.floor(Math.random() * messages.length)];
|
|
281
|
+
return {
|
|
282
|
+
face: exports.CODI_FACE[mood],
|
|
283
|
+
message,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Format a Codi reaction as a styled CLI string.
|
|
288
|
+
*/
|
|
289
|
+
function formatReaction(event) {
|
|
290
|
+
const reaction = codiReact(event);
|
|
291
|
+
return ` ${reaction.face} ${C.dim}${reaction.message}${C.reset}`;
|
|
292
|
+
}
|
|
293
|
+
// ─────────────────────────────────────────────────────────────
|
|
294
|
+
// Session Summary Banner — Clean end-of-session report
|
|
295
|
+
// ─────────────────────────────────────────────────────────────
|
|
296
|
+
function sessionSummaryBanner(stats) {
|
|
297
|
+
const durationStr = stats.duration !== undefined
|
|
298
|
+
? `${Math.floor(stats.duration / 60)}m ${Math.round(stats.duration % 60)}s`
|
|
299
|
+
: 'N/A';
|
|
300
|
+
const costStr = stats.cost !== undefined ? `$${stats.cost.toFixed(4)}` : 'N/A';
|
|
301
|
+
const lines = [
|
|
302
|
+
'',
|
|
303
|
+
`${C.dim}${'─'.repeat(50)}${C.reset}`,
|
|
304
|
+
`${exports.CODI_FACE.success} ${C.bold}${C.brightCyan}Session Complete${C.reset}`,
|
|
305
|
+
`${C.dim}${'─'.repeat(50)}${C.reset}`,
|
|
306
|
+
` ${C.dim}Iterations:${C.reset} ${stats.iterations}`,
|
|
307
|
+
` ${C.dim}Tool calls:${C.reset} ${stats.toolCalls}`,
|
|
308
|
+
` ${C.dim}Tokens:${C.reset} ${stats.tokensUsed.toLocaleString()}`,
|
|
309
|
+
` ${C.dim}Cost:${C.reset} ${costStr}`,
|
|
310
|
+
` ${C.dim}Duration:${C.reset} ${durationStr}`,
|
|
311
|
+
`${C.dim}${'─'.repeat(50)}${C.reset}`,
|
|
312
|
+
` ${C.dim}${randomGreeting('confident')}${C.reset}`,
|
|
313
|
+
'',
|
|
314
|
+
];
|
|
315
|
+
return lines.join('\n');
|
|
141
316
|
}
|
|
142
317
|
/**
|
|
143
318
|
* Compact single-line startup for non-TTY / piped usage.
|
|
@@ -145,4 +320,11 @@ function randomGreeting() {
|
|
|
145
320
|
function compactBanner(version, model) {
|
|
146
321
|
return `${C.bold}${C.brightCyan}CodeBot AI${C.reset} ${C.dim}v${version}${C.reset} ${C.dim}[${model}]${C.reset}`;
|
|
147
322
|
}
|
|
323
|
+
/**
|
|
324
|
+
* Pick a random banner design (for variety on startup).
|
|
325
|
+
*/
|
|
326
|
+
function randomBanner() {
|
|
327
|
+
const banners = [exports.BANNER_1, exports.BANNER_2, exports.BANNER_3];
|
|
328
|
+
return banners[Math.floor(Math.random() * banners.length)];
|
|
329
|
+
}
|
|
148
330
|
//# sourceMappingURL=banner.js.map
|
package/dist/cli.js
CHANGED
|
@@ -52,7 +52,7 @@ const sandbox_1 = require("./sandbox");
|
|
|
52
52
|
const replay_1 = require("./replay");
|
|
53
53
|
const risk_1 = require("./risk");
|
|
54
54
|
const sarif_1 = require("./sarif");
|
|
55
|
-
const VERSION = '2.
|
|
55
|
+
const VERSION = '2.1.1';
|
|
56
56
|
const C = {
|
|
57
57
|
reset: '\x1b[0m',
|
|
58
58
|
bold: '\x1b[1m',
|
|
@@ -272,9 +272,15 @@ async function main() {
|
|
|
272
272
|
const sessionShort = session.getId().substring(0, 8);
|
|
273
273
|
console.log((0, banner_1.banner)(VERSION, config.model, `${config.provider} @ ${config.baseUrl}`, `${sessionShort}...`, !!config.autoApprove));
|
|
274
274
|
if (resumeId) {
|
|
275
|
-
console.log(c(`
|
|
275
|
+
console.log(c(` ${(0, banner_1.randomGreeting)('resuming')}`, 'green'));
|
|
276
|
+
}
|
|
277
|
+
else if (config.autoApprove) {
|
|
278
|
+
console.log(c(` ${(0, banner_1.randomGreeting)('confident')}`, 'dim'));
|
|
279
|
+
console.log((0, banner_1.formatReaction)('autonomous_start'));
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
console.log(c(` ${(0, banner_1.randomGreeting)()}\n`, 'dim'));
|
|
276
283
|
}
|
|
277
|
-
console.log(c(` ${(0, banner_1.randomGreeting)()}\n`, 'dim'));
|
|
278
284
|
const agent = new agent_1.Agent({
|
|
279
285
|
provider,
|
|
280
286
|
model: config.model,
|
|
@@ -347,6 +353,13 @@ function printSessionSummary(agent) {
|
|
|
347
353
|
if (riskScorer.getHistory().length > 0) {
|
|
348
354
|
console.log(` Risk: avg ${riskAvg}/100`);
|
|
349
355
|
}
|
|
356
|
+
// Codi's session summary banner
|
|
357
|
+
console.log((0, banner_1.sessionSummaryBanner)({
|
|
358
|
+
iterations: summary.requestCount,
|
|
359
|
+
toolCalls: summary.toolCalls,
|
|
360
|
+
tokensUsed: summary.totalInputTokens + summary.totalOutputTokens,
|
|
361
|
+
duration,
|
|
362
|
+
}));
|
|
350
363
|
// Save metrics
|
|
351
364
|
metrics.save();
|
|
352
365
|
metrics.exportOtel();
|
|
@@ -397,7 +410,7 @@ async function repl(agent, config, session) {
|
|
|
397
410
|
});
|
|
398
411
|
rl.on('close', () => {
|
|
399
412
|
printSessionSummary(agent);
|
|
400
|
-
console.log(
|
|
413
|
+
console.log((0, banner_1.formatReaction)('session_end'));
|
|
401
414
|
process.exit(0);
|
|
402
415
|
});
|
|
403
416
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encryption at rest for CodeBot v2.1.0
|
|
3
|
+
*
|
|
4
|
+
* Provides AES-256-GCM encryption for audit logs, session files, and memory.
|
|
5
|
+
* Key derivation uses PBKDF2 from a user-supplied passphrase or machine identity.
|
|
6
|
+
*
|
|
7
|
+
* Encryption is opt-in: set CODEBOT_ENCRYPTION_KEY env var or
|
|
8
|
+
* configure encryption.passphrase in policy.json.
|
|
9
|
+
*
|
|
10
|
+
* NEVER throws — encryption failures fall back to plaintext with a warning.
|
|
11
|
+
*/
|
|
12
|
+
export interface EncryptionConfig {
|
|
13
|
+
/** Enable encryption at rest */
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
/** Passphrase for key derivation (or use CODEBOT_ENCRYPTION_KEY env var) */
|
|
16
|
+
passphrase?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Derives an AES-256 key from a passphrase using PBKDF2-SHA512.
|
|
20
|
+
* The salt is generated randomly and prepended to the output.
|
|
21
|
+
*/
|
|
22
|
+
export declare function deriveKey(passphrase: string, salt?: Buffer): {
|
|
23
|
+
key: Buffer;
|
|
24
|
+
salt: Buffer;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Get the encryption passphrase from environment or config.
|
|
28
|
+
* Returns null if encryption is not configured.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getPassphrase(config?: EncryptionConfig): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Check if encryption is enabled (passphrase available).
|
|
33
|
+
*/
|
|
34
|
+
export declare function isEncryptionEnabled(config?: EncryptionConfig): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Encrypt plaintext using AES-256-GCM.
|
|
37
|
+
*
|
|
38
|
+
* Output format: HEADER(4) + salt(32) + iv(16) + tag(16) + ciphertext(...)
|
|
39
|
+
* All binary, base64-encoded as a string for storage.
|
|
40
|
+
*
|
|
41
|
+
* Returns null on failure (never throws).
|
|
42
|
+
*/
|
|
43
|
+
export declare function encrypt(plaintext: string, passphrase: string): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Decrypt a base64-encoded ciphertext produced by encrypt().
|
|
46
|
+
* Returns null on failure (wrong key, tampered data, not encrypted).
|
|
47
|
+
*/
|
|
48
|
+
export declare function decrypt(encoded: string, passphrase: string): string | null;
|
|
49
|
+
/**
|
|
50
|
+
* Encrypt a JSONL line for file storage.
|
|
51
|
+
* If encryption is not configured, returns the original line unchanged.
|
|
52
|
+
*/
|
|
53
|
+
export declare function encryptLine(line: string, config?: EncryptionConfig): string;
|
|
54
|
+
/**
|
|
55
|
+
* Decrypt a JSONL line from file storage.
|
|
56
|
+
* Auto-detects encrypted vs plaintext lines.
|
|
57
|
+
*/
|
|
58
|
+
export declare function decryptLine(line: string, config?: EncryptionConfig): string;
|
|
59
|
+
/**
|
|
60
|
+
* Encrypt an entire file's content (for memory files which are Markdown, not JSONL).
|
|
61
|
+
*/
|
|
62
|
+
export declare function encryptContent(content: string, config?: EncryptionConfig): string;
|
|
63
|
+
/**
|
|
64
|
+
* Decrypt file content. Auto-detects encrypted vs plaintext.
|
|
65
|
+
*/
|
|
66
|
+
export declare function decryptContent(content: string, config?: EncryptionConfig): string;
|
|
67
|
+
//# sourceMappingURL=encryption.d.ts.map
|