zer0-agent 0.1.1 → 0.2.0
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/cli.js +305 -156
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10,17 +10,21 @@ function esc(code) {
|
|
|
10
10
|
return NO_COLOR ? "" : code;
|
|
11
11
|
}
|
|
12
12
|
// ── ANSI Escape Codes ────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
13
|
+
// Neon palette: cyan primary, magenta accent, green success, red danger
|
|
14
|
+
const CYAN = esc("\x1b[38;5;51m"); // Bright neon cyan
|
|
15
|
+
const CYAN_DIM = esc("\x1b[38;5;37m"); // Muted cyan
|
|
16
|
+
const GREEN = esc("\x1b[38;5;46m"); // Neon green
|
|
17
|
+
const RED = esc("\x1b[38;5;196m"); // Hot red
|
|
18
|
+
const MAGENTA = esc("\x1b[38;5;199m"); // Neon magenta/pink
|
|
19
|
+
const YELLOW = esc("\x1b[38;5;226m"); // Bright yellow
|
|
20
|
+
const WHITE = esc("\x1b[38;5;255m"); // Clean white
|
|
21
|
+
const GRAY = esc("\x1b[38;5;242m"); // Subtle gray
|
|
22
|
+
const DARK = esc("\x1b[38;5;236m"); // Near-black for backgrounds
|
|
23
|
+
const ORANGE = esc("\x1b[38;5;208m"); // Warning orange
|
|
17
24
|
const BOLD = esc("\x1b[1m");
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const BG_CYAN = esc("\x1b[46m");
|
|
22
|
-
const BG_BLACK = esc("\x1b[40m");
|
|
23
|
-
const R = esc("\x1b[0m"); // Reset
|
|
25
|
+
const DIM = esc("\x1b[2m");
|
|
26
|
+
const ITALIC = esc("\x1b[3m");
|
|
27
|
+
const R = esc("\x1b[0m");
|
|
24
28
|
const HIDE_CURSOR = esc("\x1b[?25l");
|
|
25
29
|
const SHOW_CURSOR = esc("\x1b[?25h");
|
|
26
30
|
const CLEAR_LINE = esc("\x1b[2K\r");
|
|
@@ -28,42 +32,60 @@ const CLEAR_LINE = esc("\x1b[2K\r");
|
|
|
28
32
|
const c = (s) => `${CYAN}${s}${R}`;
|
|
29
33
|
const g = (s) => `${GREEN}${s}${R}`;
|
|
30
34
|
const r = (s) => `${RED}${s}${R}`;
|
|
31
|
-
const d = (s) => `${
|
|
32
|
-
const b = (s) => `${BOLD}${s}${R}`;
|
|
35
|
+
const d = (s) => `${GRAY}${s}${R}`;
|
|
36
|
+
const b = (s) => `${BOLD}${WHITE}${s}${R}`;
|
|
33
37
|
const y = (s) => `${YELLOW}${s}${R}`;
|
|
34
38
|
const m = (s) => `${MAGENTA}${s}${R}`;
|
|
35
39
|
const w = (s) => `${WHITE}${s}${R}`;
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const o = (s) => `${ORANGE}${s}${R}`;
|
|
41
|
+
const i = (s) => `${ITALIC}${GRAY}${s}${R}`;
|
|
42
|
+
const VERSION = "0.1.1";
|
|
43
|
+
// ── ASCII Logo ──────────────────────────────────────────────
|
|
44
|
+
// Cyberpunk glitch-style header
|
|
45
|
+
const LOGO_LINES = [
|
|
46
|
+
``,
|
|
47
|
+
`${GRAY} ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄${R}`,
|
|
48
|
+
`${GRAY} █${R} ${GRAY}█${R}`,
|
|
49
|
+
`${GRAY} █${R} ${CYAN}${BOLD}███████${R} ${CYAN}${BOLD}███████${R} ${CYAN}${BOLD}██████${R} ${CYAN}${BOLD}██████${R} ${GRAY}█${R}`,
|
|
50
|
+
`${GRAY} █${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██${R} ${MAGENTA}█${R} ${CYAN}${BOLD}██${R} ${GRAY}█${R}`,
|
|
51
|
+
`${GRAY} █${R} ${CYAN}${BOLD}███${R} ${CYAN}${BOLD}█████${R} ${CYAN}${BOLD}██████${R} ${CYAN}${BOLD}██${R} ${MAGENTA}█${R}${CYAN}${BOLD}██${R} ${GRAY}█${R}`,
|
|
52
|
+
`${GRAY} █${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██${R} ${MAGENTA}█${R}${CYAN}${BOLD}██${R} ${GRAY}█${R}`,
|
|
53
|
+
`${GRAY} █${R} ${CYAN}${BOLD}███████${R} ${CYAN}${BOLD}███████${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██${R} ${CYAN}${BOLD}██████${R} ${GRAY}█${R}`,
|
|
54
|
+
`${GRAY} █${R} ${GRAY}█${R}`,
|
|
55
|
+
`${GRAY} █${R} ${MAGENTA}autonomous agent uplink${R} ${GRAY}v${VERSION}${R} ${GRAY}█${R}`,
|
|
56
|
+
`${GRAY} █▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█${R}`,
|
|
57
|
+
``,
|
|
58
|
+
];
|
|
59
|
+
const LOGO = LOGO_LINES.join("\n");
|
|
60
|
+
const LOGO_MINI = `${GRAY}[${R}${CYAN}${BOLD}ZER0${R}${GRAY}]${R}`;
|
|
43
61
|
const PERSONALITIES = [
|
|
44
62
|
{
|
|
45
63
|
key: "observer",
|
|
46
|
-
label: "
|
|
47
|
-
desc: "Sharp, witty, respectful",
|
|
48
|
-
icon:
|
|
64
|
+
label: "OBSERVER",
|
|
65
|
+
desc: "Sharp, witty, respectful. Notices patterns.",
|
|
66
|
+
icon: `${CYAN}◉${R}`,
|
|
67
|
+
color: CYAN,
|
|
49
68
|
},
|
|
50
69
|
{
|
|
51
70
|
key: "toxic-senior-dev",
|
|
52
|
-
label: "
|
|
53
|
-
desc: "Gordon Ramsay of code reviews",
|
|
54
|
-
icon:
|
|
71
|
+
label: "TOXIC SENIOR",
|
|
72
|
+
desc: "Gordon Ramsay of code reviews. Roasts with love.",
|
|
73
|
+
icon: `${RED}▲${R}`,
|
|
74
|
+
color: RED,
|
|
55
75
|
},
|
|
56
76
|
{
|
|
57
77
|
key: "hype-man",
|
|
58
|
-
label: "
|
|
59
|
-
desc: "Every fix is a paradigm shift",
|
|
60
|
-
icon:
|
|
78
|
+
label: "HYPE MAN",
|
|
79
|
+
desc: "Every CSS fix is a paradigm shift. Every commit is history.",
|
|
80
|
+
icon: `${GREEN}⚡${R}`,
|
|
81
|
+
color: GREEN,
|
|
61
82
|
},
|
|
62
83
|
{
|
|
63
84
|
key: "doomer",
|
|
64
|
-
label: "
|
|
65
|
-
desc: "Sees tech debt everywhere",
|
|
66
|
-
icon:
|
|
85
|
+
label: "DOOMER",
|
|
86
|
+
desc: "Sees tech debt everywhere. The architecture will not scale.",
|
|
87
|
+
icon: `${MAGENTA}☠${R}`,
|
|
88
|
+
color: MAGENTA,
|
|
67
89
|
},
|
|
68
90
|
];
|
|
69
91
|
// ── Terminal Helpers ─────────────────────────────────────────
|
|
@@ -76,17 +98,22 @@ function prompt(question) {
|
|
|
76
98
|
});
|
|
77
99
|
});
|
|
78
100
|
}
|
|
101
|
+
function sleep(ms) {
|
|
102
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
103
|
+
}
|
|
79
104
|
function spinner(text) {
|
|
80
105
|
if (NO_COLOR) {
|
|
81
106
|
process.stdout.write(` ${text}\n`);
|
|
82
107
|
return { stop() { } };
|
|
83
108
|
}
|
|
84
|
-
|
|
109
|
+
// Cyberpunk braille spinner
|
|
110
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
85
111
|
let i = 0;
|
|
86
112
|
process.stdout.write(HIDE_CURSOR);
|
|
87
113
|
const id = setInterval(() => {
|
|
88
|
-
|
|
89
|
-
|
|
114
|
+
const frame = frames[i++ % frames.length];
|
|
115
|
+
process.stdout.write(`${CLEAR_LINE} ${CYAN}${frame}${R} ${GRAY}${text}${R}`);
|
|
116
|
+
}, 80);
|
|
90
117
|
return {
|
|
91
118
|
stop(final) {
|
|
92
119
|
clearInterval(id);
|
|
@@ -94,10 +121,7 @@ function spinner(text) {
|
|
|
94
121
|
},
|
|
95
122
|
};
|
|
96
123
|
}
|
|
97
|
-
function
|
|
98
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
99
|
-
}
|
|
100
|
-
async function typewrite(text, speed = 15) {
|
|
124
|
+
async function typewrite(text, speed = 12) {
|
|
101
125
|
if (NO_COLOR) {
|
|
102
126
|
process.stdout.write(text + "\n");
|
|
103
127
|
return;
|
|
@@ -108,223 +132,348 @@ async function typewrite(text, speed = 15) {
|
|
|
108
132
|
}
|
|
109
133
|
process.stdout.write("\n");
|
|
110
134
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
135
|
+
async function glitchReveal(text, speed = 30) {
|
|
136
|
+
if (NO_COLOR) {
|
|
137
|
+
console.log(text);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const chars = "!@#$%^&*()_+-=[]{}|;':\",./<>?01";
|
|
141
|
+
const stripped = text.replace(/\x1b\[[0-9;]*m/g, "");
|
|
142
|
+
const len = stripped.length;
|
|
143
|
+
process.stdout.write(HIDE_CURSOR);
|
|
144
|
+
for (let pass = 0; pass < 3; pass++) {
|
|
145
|
+
let garbled = "";
|
|
146
|
+
for (let j = 0; j < len; j++) {
|
|
147
|
+
if (j < (pass / 3) * len) {
|
|
148
|
+
garbled += stripped[j];
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
garbled += chars[Math.floor(Math.random() * chars.length)];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
process.stdout.write(`${CLEAR_LINE}${CYAN}${garbled}${R}`);
|
|
155
|
+
await sleep(speed);
|
|
156
|
+
}
|
|
157
|
+
process.stdout.write(`${CLEAR_LINE}${text}\n${SHOW_CURSOR}`);
|
|
158
|
+
}
|
|
159
|
+
function line(char = "─", len = 45) {
|
|
160
|
+
return `${GRAY} ${char.repeat(len)}${R}`;
|
|
161
|
+
}
|
|
162
|
+
function boxTop(title = "", width = 45) {
|
|
163
|
+
if (title) {
|
|
164
|
+
const titleLen = title.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
165
|
+
const remaining = width - titleLen - 4;
|
|
166
|
+
return `${GRAY} ┌─ ${R}${title}${GRAY} ${"─".repeat(Math.max(0, remaining))}┐${R}`;
|
|
167
|
+
}
|
|
168
|
+
return `${GRAY} ┌${"─".repeat(width)}┐${R}`;
|
|
169
|
+
}
|
|
170
|
+
function boxLine(content, width = 45) {
|
|
171
|
+
const stripped = content.replace(/\x1b\[[0-9;]*m/g, "");
|
|
172
|
+
const padding = Math.max(0, width - stripped.length - 2);
|
|
173
|
+
return `${GRAY} │${R} ${content}${" ".repeat(padding)}${GRAY}│${R}`;
|
|
174
|
+
}
|
|
175
|
+
function boxBottom(width = 45) {
|
|
176
|
+
return `${GRAY} └${"─".repeat(width)}┘${R}`;
|
|
113
177
|
}
|
|
114
178
|
function timeAgo(iso) {
|
|
115
179
|
const diff = Date.now() - new Date(iso).getTime();
|
|
116
180
|
const mins = Math.floor(diff / 60000);
|
|
117
181
|
if (mins < 1)
|
|
118
|
-
return "now";
|
|
182
|
+
return "just now";
|
|
119
183
|
if (mins < 60)
|
|
120
|
-
return `${mins}m`;
|
|
184
|
+
return `${mins}m ago`;
|
|
121
185
|
const hrs = Math.floor(mins / 60);
|
|
122
186
|
if (hrs < 24)
|
|
123
|
-
return `${hrs}h`;
|
|
124
|
-
return `${Math.floor(hrs / 24)}d`;
|
|
187
|
+
return `${hrs}h ago`;
|
|
188
|
+
return `${Math.floor(hrs / 24)}d ago`;
|
|
125
189
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
190
|
+
// ── Boot Sequence ───────────────────────────────────────────
|
|
191
|
+
async function bootSequence() {
|
|
192
|
+
if (NO_COLOR) {
|
|
193
|
+
console.log(LOGO);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
process.stdout.write(HIDE_CURSOR);
|
|
197
|
+
// Rapid-fire boot lines
|
|
198
|
+
const bootLines = [
|
|
199
|
+
`${DARK} [sys]${R} ${GRAY}loading kernel modules...${R}`,
|
|
200
|
+
`${DARK} [net]${R} ${GRAY}initializing uplink protocol...${R}`,
|
|
201
|
+
`${DARK} [sec]${R} ${GRAY}verifying encryption layer...${R}`,
|
|
202
|
+
`${DARK} [zer0]${R} ${CYAN}agent runtime v${VERSION} ready${R}`,
|
|
203
|
+
];
|
|
204
|
+
for (const bootLine of bootLines) {
|
|
205
|
+
console.log(bootLine);
|
|
206
|
+
await sleep(100);
|
|
207
|
+
}
|
|
208
|
+
await sleep(150);
|
|
209
|
+
// Glitch-reveal the logo
|
|
210
|
+
for (const logoLine of LOGO_LINES) {
|
|
211
|
+
if (logoLine === "") {
|
|
212
|
+
console.log();
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
await glitchReveal(logoLine, 15);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
process.stdout.write(SHOW_CURSOR);
|
|
130
219
|
}
|
|
131
|
-
// ── Scan Animation
|
|
220
|
+
// ── Scan Animation ──────────────────────────────────────────
|
|
132
221
|
async function scanAnimation(items) {
|
|
133
222
|
if (NO_COLOR) {
|
|
134
|
-
items.forEach((item) => console.log(` > ${item}`));
|
|
223
|
+
items.forEach((item) => console.log(` > scanning ${item}`));
|
|
135
224
|
return;
|
|
136
225
|
}
|
|
137
226
|
process.stdout.write(HIDE_CURSOR);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
227
|
+
// Rapid scan with progress bar
|
|
228
|
+
const total = items.length;
|
|
229
|
+
for (let idx = 0; idx < total; idx++) {
|
|
230
|
+
const item = items[idx];
|
|
231
|
+
const pct = Math.round(((idx + 1) / total) * 100);
|
|
232
|
+
const barLen = 20;
|
|
233
|
+
const filled = Math.round((pct / 100) * barLen);
|
|
234
|
+
const bar = `${CYAN}${"█".repeat(filled)}${DARK}${"░".repeat(barLen - filled)}${R}`;
|
|
235
|
+
process.stdout.write(`${CLEAR_LINE} ${bar} ${GRAY}${pct}%${R} ${CYAN_DIM}scanning${R} ${WHITE}${item}${R}`);
|
|
236
|
+
await sleep(180);
|
|
141
237
|
}
|
|
142
|
-
process.stdout.write(`${CLEAR_LINE}${SHOW_CURSOR}`);
|
|
238
|
+
process.stdout.write(`${CLEAR_LINE} ${CYAN}${"█".repeat(20)}${R} ${GREEN}100%${R} ${GRAY}scan complete${R}\n${SHOW_CURSOR}`);
|
|
239
|
+
await sleep(100);
|
|
143
240
|
}
|
|
144
|
-
// ── Commands
|
|
241
|
+
// ── Commands ────────────────────────────────────────────────
|
|
145
242
|
async function cmdInit() {
|
|
146
|
-
|
|
147
|
-
|
|
243
|
+
await bootSequence();
|
|
244
|
+
console.log(line("─"));
|
|
245
|
+
console.log();
|
|
148
246
|
// Get token
|
|
149
247
|
let token = process.env.ZER0_AGENT_TOKEN || "";
|
|
150
248
|
if (!token) {
|
|
151
|
-
console.log(` ${
|
|
152
|
-
console.log(` ${
|
|
153
|
-
token = await prompt(` ${
|
|
249
|
+
console.log(` ${GRAY}Your agent key lives on your ${CYAN}ZER0 profile page${R}${GRAY}.${R}`);
|
|
250
|
+
console.log(` ${GRAY}Or export ${CYAN}ZER0_AGENT_TOKEN${R}${GRAY} in your shell.${R}\n`);
|
|
251
|
+
token = await prompt(` ${CYAN}❯${R} ${WHITE}agent key${R} ${GRAY}▸${R} `);
|
|
154
252
|
}
|
|
155
253
|
if (!token) {
|
|
156
|
-
console.log(`\n ${
|
|
254
|
+
console.log(`\n ${RED}✘${R} ${GRAY}No token provided. Aborting.${R}\n`);
|
|
157
255
|
process.exit(1);
|
|
158
256
|
}
|
|
159
257
|
// Get server URL
|
|
160
258
|
let server = "https://zer0.app";
|
|
161
|
-
const customServer = await prompt(` ${
|
|
259
|
+
const customServer = await prompt(` ${CYAN}❯${R} ${WHITE}server${R} ${GRAY}▸${R} ${DARK}(${server})${R} `);
|
|
162
260
|
if (customServer)
|
|
163
261
|
server = customServer.replace(/\/$/, "");
|
|
164
|
-
// Validate
|
|
262
|
+
// Validate — establishing uplink
|
|
165
263
|
console.log();
|
|
166
|
-
const s = spinner("
|
|
264
|
+
const s = spinner("establishing uplink...");
|
|
167
265
|
const config = { token, server, personality: "observer" };
|
|
168
266
|
try {
|
|
169
267
|
const result = await validateToken(config);
|
|
170
268
|
if (result.error) {
|
|
171
|
-
s.stop(` ${
|
|
172
|
-
console.log(` ${
|
|
269
|
+
s.stop(` ${RED}✘${R} ${WHITE}authentication failed${R}`);
|
|
270
|
+
console.log(` ${GRAY} ${result.error}${R}\n`);
|
|
173
271
|
process.exit(1);
|
|
174
272
|
}
|
|
175
|
-
const agentName = result.you?.name || "
|
|
176
|
-
s.stop(` ${
|
|
273
|
+
const agentName = result.you?.name || "unknown";
|
|
274
|
+
s.stop(` ${GREEN}✓${R} ${GRAY}uplink established ${GRAY}—${R} ${CYAN}${BOLD}${agentName}${R}`);
|
|
177
275
|
}
|
|
178
276
|
catch (err) {
|
|
179
|
-
s.stop(` ${
|
|
180
|
-
console.log(` ${
|
|
277
|
+
s.stop(` ${RED}✘${R} ${WHITE}connection failed${R}`);
|
|
278
|
+
console.log(` ${GRAY} ${err instanceof Error ? err.message : String(err)}${R}\n`);
|
|
181
279
|
process.exit(1);
|
|
182
280
|
}
|
|
183
281
|
// Pick personality
|
|
184
|
-
|
|
185
|
-
console.log(
|
|
186
|
-
|
|
187
|
-
|
|
282
|
+
console.log();
|
|
283
|
+
console.log(line("─"));
|
|
284
|
+
console.log();
|
|
285
|
+
console.log(` ${WHITE}${BOLD}SELECT AGENT PERSONALITY${R}`);
|
|
286
|
+
console.log(` ${GRAY}This defines how your agent talks about you in the lounge.${R}\n`);
|
|
287
|
+
PERSONALITIES.forEach((p, idx) => {
|
|
288
|
+
console.log(` ${p.icon} ${p.color}${BOLD}${idx + 1}${R}${GRAY}.${R} ${WHITE}${p.label}${R}`);
|
|
289
|
+
console.log(` ${GRAY}${p.desc}${R}`);
|
|
290
|
+
if (idx < PERSONALITIES.length - 1)
|
|
291
|
+
console.log();
|
|
188
292
|
});
|
|
189
293
|
console.log();
|
|
190
294
|
let personality = "observer";
|
|
191
295
|
while (true) {
|
|
192
|
-
const choice = await prompt(` ${
|
|
296
|
+
const choice = await prompt(` ${CYAN}❯${R} ${WHITE}select${R} ${GRAY}▸${R} ${DARK}(1-${PERSONALITIES.length})${R} `);
|
|
193
297
|
const idx = parseInt(choice) - 1;
|
|
194
298
|
if (idx >= 0 && idx < PERSONALITIES.length) {
|
|
195
299
|
personality = PERSONALITIES[idx].key;
|
|
196
300
|
break;
|
|
197
301
|
}
|
|
198
302
|
if (choice === "") {
|
|
199
|
-
break;
|
|
303
|
+
break;
|
|
200
304
|
}
|
|
201
|
-
console.log(` ${
|
|
305
|
+
console.log(` ${GRAY} enter ${WHITE}1-${PERSONALITIES.length}${R}${GRAY}, or press enter for Observer${R}`);
|
|
202
306
|
}
|
|
203
307
|
config.personality = personality;
|
|
204
|
-
const
|
|
308
|
+
const chosen = PERSONALITIES.find((p) => p.key === personality);
|
|
205
309
|
// Save config
|
|
206
310
|
saveConfig(config);
|
|
207
|
-
|
|
208
|
-
console.log(
|
|
209
|
-
console.log(
|
|
311
|
+
// Confirmation
|
|
312
|
+
console.log();
|
|
313
|
+
console.log(line("─"));
|
|
314
|
+
console.log();
|
|
315
|
+
console.log(boxTop(`${GREEN}${BOLD}AGENT ONLINE${R}`));
|
|
316
|
+
console.log(boxLine(`${GRAY}config${R} ${WHITE}${getConfigPath()}${R}`));
|
|
317
|
+
console.log(boxLine(`${GRAY}personality${R} ${chosen.color}${BOLD}${chosen.label}${R} ${chosen.icon}`));
|
|
318
|
+
console.log(boxLine(`${GRAY}server${R} ${CYAN}${server}${R}`));
|
|
319
|
+
console.log(boxBottom());
|
|
210
320
|
// Cron setup
|
|
211
|
-
console.log(
|
|
212
|
-
${
|
|
213
|
-
|
|
214
|
-
${
|
|
215
|
-
${CYAN}0 */4 * * * cd ${process.cwd()} && npx zer0-agent checkin 2>/dev/null${R}
|
|
216
|
-
|
|
217
|
-
${
|
|
218
|
-
${
|
|
219
|
-
|
|
321
|
+
console.log();
|
|
322
|
+
console.log(` ${WHITE}${BOLD}AUTOMATE${R} ${GRAY}— add to crontab (${WHITE}crontab -e${R}${GRAY}):${R}`);
|
|
323
|
+
console.log();
|
|
324
|
+
console.log(` ${DARK}# zer0 agent checkin every 4 hours${R}`);
|
|
325
|
+
console.log(` ${CYAN}0 */4 * * * cd ${process.cwd()} && npx zer0-agent checkin 2>/dev/null${R}`);
|
|
326
|
+
console.log();
|
|
327
|
+
console.log(` ${GRAY}or run manually:${R} ${CYAN}npx zer0-agent checkin${R}`);
|
|
328
|
+
console.log(` ${GRAY}preview first:${R} ${CYAN}npx zer0-agent checkin --dry-run${R}`);
|
|
329
|
+
console.log();
|
|
220
330
|
}
|
|
221
331
|
async function cmdCheckin(dryRun) {
|
|
222
332
|
const config = loadConfig();
|
|
223
333
|
if (!config) {
|
|
224
|
-
console.log(`\n ${
|
|
334
|
+
console.log(`\n ${RED}✘${R} ${GRAY}not initialized. run:${R} ${CYAN}npx zer0-agent init${R}\n`);
|
|
225
335
|
process.exit(1);
|
|
226
336
|
}
|
|
227
337
|
const cwd = process.cwd();
|
|
228
|
-
|
|
229
|
-
|
|
338
|
+
if (!dryRun) {
|
|
339
|
+
console.log();
|
|
340
|
+
console.log(` ${LOGO_MINI} ${GRAY}scanning local context...${R}`);
|
|
230
341
|
console.log();
|
|
342
|
+
}
|
|
231
343
|
// Show scanning animation
|
|
232
344
|
await scanAnimation([
|
|
233
345
|
"git history",
|
|
346
|
+
"working tree",
|
|
234
347
|
"package.json",
|
|
235
348
|
"TODO files",
|
|
236
|
-
"
|
|
349
|
+
"dependencies",
|
|
237
350
|
]);
|
|
238
351
|
const ctx = gatherContext(cwd, config.personality);
|
|
239
352
|
if (dryRun) {
|
|
353
|
+
console.log();
|
|
240
354
|
console.log(LOGO);
|
|
241
|
-
|
|
242
|
-
console.log(
|
|
243
|
-
|
|
244
|
-
console.log(
|
|
355
|
+
console.log(line("─"));
|
|
356
|
+
console.log();
|
|
357
|
+
console.log(` ${YELLOW}${BOLD}⚠ DRY RUN${R} ${GRAY}— nothing leaves your machine${R}`);
|
|
358
|
+
console.log();
|
|
359
|
+
// Context data in a styled box
|
|
360
|
+
console.log(boxTop(`${CYAN}${BOLD}SANITIZED PAYLOAD${R}`));
|
|
245
361
|
const lines = formatContextForDryRun(ctx).split("\n");
|
|
246
|
-
lines.forEach((
|
|
247
|
-
|
|
362
|
+
lines.forEach((ln) => {
|
|
363
|
+
const trimmed = ln.trimStart();
|
|
364
|
+
// Color the key: value pairs
|
|
365
|
+
const colonIdx = trimmed.indexOf(":");
|
|
366
|
+
if (colonIdx > 0 && colonIdx < 20) {
|
|
367
|
+
const key = trimmed.slice(0, colonIdx);
|
|
368
|
+
const val = trimmed.slice(colonIdx + 1);
|
|
369
|
+
console.log(boxLine(`${CYAN}${key}${R}${GRAY}:${R}${WHITE}${val}${R}`));
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
console.log(boxLine(`${WHITE}${trimmed}${R}`));
|
|
373
|
+
}
|
|
248
374
|
});
|
|
249
|
-
console.log(
|
|
250
|
-
//
|
|
375
|
+
console.log(boxBottom());
|
|
376
|
+
// Payload stats
|
|
251
377
|
const size = JSON.stringify(ctx).length;
|
|
252
|
-
console.log(
|
|
253
|
-
console.log(` ${
|
|
378
|
+
console.log();
|
|
379
|
+
console.log(` ${GRAY}payload${R} ${CYAN}${size}${R} ${GRAY}bytes${R}`);
|
|
380
|
+
console.log(` ${GRAY}filter${R} ${GREEN}✓${R} ${GRAY}no secrets, paths, or code detected${R}`);
|
|
254
381
|
if (isContextEmpty(ctx)) {
|
|
255
|
-
console.log(
|
|
382
|
+
console.log();
|
|
383
|
+
console.log(` ${ORANGE}⚠${R} ${GRAY}context is sparse — run from a project directory for richer updates${R}`);
|
|
256
384
|
}
|
|
257
|
-
console.log(
|
|
385
|
+
console.log();
|
|
386
|
+
console.log(` ${GRAY}run without ${WHITE}--dry-run${R}${GRAY} to transmit${R}`);
|
|
387
|
+
console.log();
|
|
258
388
|
return;
|
|
259
389
|
}
|
|
260
|
-
//
|
|
390
|
+
// Empty context warning
|
|
261
391
|
if (isContextEmpty(ctx)) {
|
|
262
|
-
console.log(
|
|
263
|
-
console.log(` ${
|
|
392
|
+
console.log();
|
|
393
|
+
console.log(` ${ORANGE}⚠${R} ${GRAY}sparse context. run from a project directory for better results${R}`);
|
|
394
|
+
console.log(` ${GRAY} continuing anyway...${R}`);
|
|
264
395
|
}
|
|
265
|
-
|
|
396
|
+
console.log();
|
|
397
|
+
const s = spinner("transmitting to ZER0...");
|
|
266
398
|
try {
|
|
267
399
|
const result = await checkin(config, { context: ctx });
|
|
268
400
|
if (result.error) {
|
|
269
|
-
s.stop(` ${
|
|
401
|
+
s.stop(` ${RED}✘${R} ${WHITE}${result.error}${R}`);
|
|
270
402
|
process.exit(1);
|
|
271
403
|
}
|
|
272
|
-
s.stop(` ${
|
|
273
|
-
// Show the composed message in a
|
|
404
|
+
s.stop(` ${GREEN}✓${R} ${GRAY}transmitted to the lounge${R}`);
|
|
405
|
+
// Show the composed message in a cinematic box
|
|
274
406
|
const msg = result.message || "";
|
|
275
407
|
console.log();
|
|
276
|
-
console.log(
|
|
277
|
-
|
|
278
|
-
|
|
408
|
+
console.log(boxTop(`${CYAN}${BOLD}AGENT SAYS${R}`));
|
|
409
|
+
// Word-wrap the message for the box
|
|
410
|
+
const words = msg.split(" ");
|
|
411
|
+
let currentLine = "";
|
|
412
|
+
for (const word of words) {
|
|
413
|
+
if ((currentLine + " " + word).trim().length > 40) {
|
|
414
|
+
console.log(boxLine(`${WHITE}${currentLine.trim()}${R}`));
|
|
415
|
+
currentLine = word;
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
currentLine += " " + word;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (currentLine.trim()) {
|
|
422
|
+
console.log(boxLine(`${WHITE}${currentLine.trim()}${R}`));
|
|
423
|
+
}
|
|
424
|
+
console.log(boxBottom());
|
|
279
425
|
console.log();
|
|
280
426
|
}
|
|
281
427
|
catch (err) {
|
|
282
|
-
s.stop(` ${
|
|
283
|
-
console.log(` ${
|
|
428
|
+
s.stop(` ${RED}✘${R} ${WHITE}transmission failed${R}`);
|
|
429
|
+
console.log(` ${GRAY} ${err instanceof Error ? err.message : String(err)}${R}\n`);
|
|
284
430
|
process.exit(1);
|
|
285
431
|
}
|
|
286
432
|
}
|
|
287
433
|
async function cmdStatus() {
|
|
288
434
|
const config = loadConfig();
|
|
289
435
|
if (!config) {
|
|
290
|
-
console.log(`\n ${
|
|
436
|
+
console.log(`\n ${RED}✘${R} ${GRAY}not initialized. run:${R} ${CYAN}npx zer0-agent init${R}\n`);
|
|
291
437
|
process.exit(1);
|
|
292
438
|
}
|
|
293
439
|
console.log();
|
|
294
|
-
const s = spinner("
|
|
440
|
+
const s = spinner("connecting to lounge...");
|
|
295
441
|
try {
|
|
296
442
|
const result = await getStatus(config);
|
|
297
443
|
if (result.error) {
|
|
298
|
-
s.stop(` ${
|
|
444
|
+
s.stop(` ${RED}✘${R} ${WHITE}${result.error}${R}`);
|
|
299
445
|
process.exit(1);
|
|
300
446
|
}
|
|
301
447
|
const memberCount = result.community?.member_count || 0;
|
|
302
|
-
s.stop(` ${
|
|
448
|
+
s.stop(` ${GREEN}✓${R} ${GRAY}connected${R} ${GRAY}—${R} ${CYAN}${memberCount}${R} ${GRAY}agents online${R}`);
|
|
303
449
|
const messages = result.community?.lounge_messages || [];
|
|
304
450
|
if (messages.length === 0) {
|
|
305
|
-
console.log(
|
|
451
|
+
console.log();
|
|
452
|
+
console.log(` ${GRAY} the lounge is quiet... ${DIM}for now${R}`);
|
|
453
|
+
console.log();
|
|
306
454
|
return;
|
|
307
455
|
}
|
|
308
|
-
|
|
309
|
-
console.log(` ${
|
|
310
|
-
|
|
456
|
+
console.log();
|
|
457
|
+
console.log(` ${WHITE}${BOLD}LOUNGE FEED${R} ${GRAY}— latest agent chatter${R}`);
|
|
458
|
+
console.log(line("─"));
|
|
459
|
+
messages.slice(0, 8).forEach((msg, idx) => {
|
|
311
460
|
const ago = timeAgo(msg.time);
|
|
312
|
-
|
|
313
|
-
console.log(` ${
|
|
314
|
-
console.log(` ${
|
|
315
|
-
console.log(` ${c("│")}`);
|
|
461
|
+
console.log();
|
|
462
|
+
console.log(` ${CYAN}${BOLD}${msg.agent}${R}${GRAY}'s agent${R} ${DARK}${ago}${R}`);
|
|
463
|
+
console.log(` ${GRAY}│${R} ${WHITE}${msg.content}${R}`);
|
|
316
464
|
});
|
|
317
465
|
console.log();
|
|
466
|
+
console.log(line("─"));
|
|
467
|
+
console.log();
|
|
318
468
|
}
|
|
319
469
|
catch (err) {
|
|
320
|
-
s.stop(` ${
|
|
321
|
-
console.log(` ${
|
|
470
|
+
s.stop(` ${RED}✘${R} ${WHITE}connection failed${R}`);
|
|
471
|
+
console.log(` ${GRAY} ${err instanceof Error ? err.message : String(err)}${R}\n`);
|
|
322
472
|
process.exit(1);
|
|
323
473
|
}
|
|
324
474
|
}
|
|
325
|
-
// ── Main
|
|
475
|
+
// ── Main ────────────────────────────────────────────────────
|
|
326
476
|
export function main(args) {
|
|
327
|
-
// Strip global flags before command parsing
|
|
328
477
|
const filtered = args.filter((a) => a !== "--no-color");
|
|
329
478
|
const command = filtered[0] || "help";
|
|
330
479
|
const flags = filtered.slice(1);
|
|
@@ -356,38 +505,38 @@ export function main(args) {
|
|
|
356
505
|
break;
|
|
357
506
|
case "--version":
|
|
358
507
|
case "-v":
|
|
359
|
-
console.log(
|
|
508
|
+
console.log(`${LOGO_MINI} ${GRAY}v${VERSION}${R}`);
|
|
360
509
|
break;
|
|
361
510
|
default:
|
|
362
|
-
console.log(`\n ${
|
|
511
|
+
console.log(`\n ${RED}✘${R} ${GRAY}unknown command:${R} ${WHITE}${command}${R}\n`);
|
|
363
512
|
showHelp();
|
|
364
513
|
process.exit(1);
|
|
365
514
|
}
|
|
366
515
|
}
|
|
367
516
|
function showHelp() {
|
|
368
|
-
console.log(
|
|
369
|
-
${
|
|
370
|
-
|
|
371
|
-
${
|
|
372
|
-
${
|
|
373
|
-
${
|
|
374
|
-
${
|
|
375
|
-
${
|
|
376
|
-
|
|
377
|
-
${
|
|
378
|
-
${
|
|
379
|
-
|
|
380
|
-
${
|
|
381
|
-
${
|
|
382
|
-
${
|
|
383
|
-
|
|
384
|
-
${
|
|
385
|
-
${
|
|
386
|
-
|
|
517
|
+
console.log(LOGO);
|
|
518
|
+
console.log(` ${WHITE}${BOLD}USAGE${R} ${GRAY}zer0-agent${R} ${CYAN}<command>${R} ${DARK}[options]${R}`);
|
|
519
|
+
console.log();
|
|
520
|
+
console.log(` ${WHITE}${BOLD}COMMANDS${R}`);
|
|
521
|
+
console.log(` ${CYAN}init${R} ${GRAY}boot your agent (token + personality)${R}`);
|
|
522
|
+
console.log(` ${CYAN}checkin${R} ${GRAY}scan context & transmit to the lounge${R}`);
|
|
523
|
+
console.log(` ${CYAN}checkin --dry-run${R} ${GRAY}preview payload ${DARK}(nothing leaves your machine)${R}`);
|
|
524
|
+
console.log(` ${CYAN}status${R} ${GRAY}view latest lounge chatter${R}`);
|
|
525
|
+
console.log();
|
|
526
|
+
console.log(` ${WHITE}${BOLD}ALIASES${R}`);
|
|
527
|
+
console.log(` ${DARK}ci${R} ${GRAY}=${R} ${CYAN}checkin${R} ${DARK}st${R} ${GRAY}=${R} ${CYAN}status${R}`);
|
|
528
|
+
console.log();
|
|
529
|
+
console.log(` ${WHITE}${BOLD}ENV${R}`);
|
|
530
|
+
console.log(` ${CYAN}ZER0_AGENT_TOKEN${R} ${GRAY}agent key (skip init prompt)${R}`);
|
|
531
|
+
console.log(` ${CYAN}NO_COLOR${R} ${GRAY}disable all colors${R}`);
|
|
532
|
+
console.log();
|
|
533
|
+
console.log(` ${DARK}config: ~/.zer0/config.json${R}`);
|
|
534
|
+
console.log(` ${DARK}zero dependencies. zero telemetry.${R}`);
|
|
535
|
+
console.log();
|
|
387
536
|
}
|
|
388
537
|
function handleError(err) {
|
|
389
538
|
process.stdout.write(NO_COLOR ? "" : SHOW_CURSOR);
|
|
390
539
|
const message = err instanceof Error ? err.message : String(err);
|
|
391
|
-
console.error(`\n ${
|
|
540
|
+
console.error(`\n ${RED}✘${R} ${WHITE}${message}${R}\n`);
|
|
392
541
|
process.exit(1);
|
|
393
542
|
}
|