@aman_asmuei/aman-agent 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Aman Asmuei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # aman-agent
2
+
3
+ Your AI companion, running locally. Powered by the aman ecosystem.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx @aman_asmuei/aman-agent
9
+ ```
10
+
11
+ First run: configure your LLM (Claude or GPT). After that, just run and talk.
12
+
13
+ ## What it does
14
+
15
+ Loads your entire aman ecosystem and runs a local AI agent:
16
+
17
+ - **Identity** (acore) — your AI knows who it is and who you are
18
+ - **Memory** (amem) — your AI remembers past sessions
19
+ - **Tools** (akit) — your AI can use GitHub, search the web, query databases
20
+ - **Workflows** (aflow) — your AI follows your defined processes
21
+ - **Guardrails** (arules) — your AI respects your boundaries
22
+ - **Skills** (askill) — your AI applies learned capabilities
23
+
24
+ ## Commands
25
+
26
+ Inside the agent:
27
+
28
+ | Command | What it does |
29
+ |:--------|:-------------|
30
+ | `/help` | Show available commands |
31
+ | `/identity` | View your AI identity |
32
+ | `/tools` | View installed tools |
33
+ | `/workflows` | View defined workflows |
34
+ | `/rules` | View guardrails |
35
+ | `/skills` | View installed skills |
36
+ | `/model` | Show current LLM model |
37
+ | `/clear` | Clear conversation history |
38
+ | `/quit` | Exit |
39
+
40
+ ## Supported LLMs
41
+
42
+ - **Claude** (Anthropic) — recommended, supports tool use
43
+ - **GPT** (OpenAI) — supports tool use
44
+ - More coming (Gemini, Ollama)
45
+
46
+ ## Configuration
47
+
48
+ Config stored in `~/.aman-agent/config.json`. Treat this file like a credential — it contains your API key.
49
+
50
+ ```json
51
+ {
52
+ "provider": "anthropic",
53
+ "apiKey": "sk-ant-...",
54
+ "model": "claude-sonnet-4-5-20250514"
55
+ }
56
+ ```
57
+
58
+ Override model per session:
59
+ ```bash
60
+ npx @aman_asmuei/aman-agent --model claude-opus-4-6
61
+ ```
62
+
63
+ ## The Ecosystem
64
+
65
+ ```
66
+ aman
67
+ ├── acore → identity
68
+ ├── amem → memory
69
+ ├── akit → tools
70
+ ├── aflow → workflows
71
+ ├── arules → guardrails
72
+ ├── aeval → evaluation
73
+ ├── askill → skills
74
+ └── aman-agent → runtime ← THIS
75
+ ```
76
+
77
+ ## License
78
+
79
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../dist/index.js";
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,631 @@
1
+ // src/index.ts
2
+ import { Command } from "commander";
3
+ import * as p from "@clack/prompts";
4
+ import pc5 from "picocolors";
5
+
6
+ // src/config.ts
7
+ import fs from "fs";
8
+ import path from "path";
9
+ import os from "os";
10
+ var CONFIG_DIR = path.join(os.homedir(), ".aman-agent");
11
+ var CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
12
+ function loadConfig() {
13
+ if (!fs.existsSync(CONFIG_PATH)) return null;
14
+ try {
15
+ return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ function saveConfig(config) {
21
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
22
+ fs.writeFileSync(
23
+ CONFIG_PATH,
24
+ JSON.stringify(config, null, 2) + "\n",
25
+ "utf-8"
26
+ );
27
+ }
28
+
29
+ // src/prompt.ts
30
+ import fs2 from "fs";
31
+ import path2 from "path";
32
+ import os2 from "os";
33
+ function assembleSystemPrompt() {
34
+ const home = os2.homedir();
35
+ const layers = [];
36
+ const parts = [];
37
+ const corePath = path2.join(home, ".acore", "core.md");
38
+ if (fs2.existsSync(corePath)) {
39
+ parts.push(fs2.readFileSync(corePath, "utf-8").trim());
40
+ layers.push("identity");
41
+ }
42
+ const contextPath = path2.join(process.cwd(), ".acore", "context.md");
43
+ if (fs2.existsSync(contextPath)) {
44
+ parts.push(fs2.readFileSync(contextPath, "utf-8").trim());
45
+ }
46
+ const kitPath = path2.join(home, ".akit", "kit.md");
47
+ if (fs2.existsSync(kitPath)) {
48
+ parts.push(fs2.readFileSync(kitPath, "utf-8").trim());
49
+ layers.push("tools");
50
+ }
51
+ const flowPath = path2.join(home, ".aflow", "flow.md");
52
+ if (fs2.existsSync(flowPath)) {
53
+ parts.push(fs2.readFileSync(flowPath, "utf-8").trim());
54
+ layers.push("workflows");
55
+ }
56
+ const rulesPath = path2.join(home, ".arules", "rules.md");
57
+ if (fs2.existsSync(rulesPath)) {
58
+ parts.push(fs2.readFileSync(rulesPath, "utf-8").trim());
59
+ layers.push("guardrails");
60
+ }
61
+ const skillsPath = path2.join(home, ".askill", "skills.md");
62
+ if (fs2.existsSync(skillsPath)) {
63
+ parts.push(fs2.readFileSync(skillsPath, "utf-8").trim());
64
+ layers.push("skills");
65
+ }
66
+ return {
67
+ prompt: parts.join("\n\n---\n\n"),
68
+ layers
69
+ };
70
+ }
71
+
72
+ // src/llm/anthropic.ts
73
+ import Anthropic from "@anthropic-ai/sdk";
74
+ function createAnthropicClient(apiKey, model) {
75
+ const client = new Anthropic({ apiKey });
76
+ return {
77
+ async chat(systemPrompt, messages, onChunk) {
78
+ let fullText = "";
79
+ try {
80
+ const stream = await client.messages.create({
81
+ model,
82
+ max_tokens: 8192,
83
+ system: systemPrompt,
84
+ messages: messages.map((m) => ({
85
+ role: m.role,
86
+ content: m.content
87
+ })),
88
+ stream: true
89
+ });
90
+ for await (const event of stream) {
91
+ if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
92
+ const text2 = event.delta.text;
93
+ fullText += text2;
94
+ onChunk({ type: "text", text: text2 });
95
+ }
96
+ }
97
+ } catch (error) {
98
+ if (error instanceof Anthropic.AuthenticationError) {
99
+ throw new Error(
100
+ "Invalid API key. Run with --model flag or delete ~/.aman-agent/config.json to reconfigure."
101
+ );
102
+ }
103
+ if (error instanceof Anthropic.RateLimitError) {
104
+ throw new Error("Rate limited by Anthropic. Please wait and retry.");
105
+ }
106
+ throw error;
107
+ }
108
+ onChunk({ type: "done" });
109
+ return { role: "assistant", content: fullText };
110
+ }
111
+ };
112
+ }
113
+
114
+ // src/llm/openai.ts
115
+ import OpenAI from "openai";
116
+ function createOpenAIClient(apiKey, model) {
117
+ const client = new OpenAI({ apiKey });
118
+ return {
119
+ async chat(systemPrompt, messages, onChunk) {
120
+ let fullText = "";
121
+ try {
122
+ const stream = await client.chat.completions.create({
123
+ model,
124
+ max_tokens: 8192,
125
+ messages: [
126
+ { role: "system", content: systemPrompt },
127
+ ...messages.map((m) => ({
128
+ role: m.role,
129
+ content: m.content
130
+ }))
131
+ ],
132
+ stream: true
133
+ });
134
+ for await (const chunk of stream) {
135
+ const text2 = chunk.choices[0]?.delta?.content || "";
136
+ if (text2) {
137
+ fullText += text2;
138
+ onChunk({ type: "text", text: text2 });
139
+ }
140
+ }
141
+ } catch (error) {
142
+ if (error instanceof OpenAI.AuthenticationError) {
143
+ throw new Error(
144
+ "Invalid API key. Run with --model flag or delete ~/.aman-agent/config.json to reconfigure."
145
+ );
146
+ }
147
+ if (error instanceof OpenAI.RateLimitError) {
148
+ throw new Error("Rate limited by OpenAI. Please wait and retry.");
149
+ }
150
+ throw error;
151
+ }
152
+ onChunk({ type: "done" });
153
+ return { role: "assistant", content: fullText };
154
+ }
155
+ };
156
+ }
157
+
158
+ // src/agent.ts
159
+ import * as readline from "readline";
160
+ import pc3 from "picocolors";
161
+
162
+ // src/commands.ts
163
+ import fs3 from "fs";
164
+ import path3 from "path";
165
+ import os3 from "os";
166
+ import pc from "picocolors";
167
+ function readEcosystemFile(filePath, label) {
168
+ if (!fs3.existsSync(filePath)) {
169
+ return pc.dim(`No ${label} file found at ${filePath}`);
170
+ }
171
+ return fs3.readFileSync(filePath, "utf-8").trim();
172
+ }
173
+ function handleCommand(input, model) {
174
+ const cmd = input.trim().toLowerCase();
175
+ const home = os3.homedir();
176
+ if (cmd === "/quit" || cmd === "/exit" || cmd === "/q") {
177
+ return { handled: true, quit: true };
178
+ }
179
+ if (cmd === "/help") {
180
+ return {
181
+ handled: true,
182
+ output: [
183
+ pc.bold("Commands:"),
184
+ ` ${pc.cyan("/help")} Show this help`,
185
+ ` ${pc.cyan("/identity")} View your AI identity`,
186
+ ` ${pc.cyan("/tools")} View installed tools`,
187
+ ` ${pc.cyan("/workflows")} View defined workflows`,
188
+ ` ${pc.cyan("/rules")} View guardrails`,
189
+ ` ${pc.cyan("/skills")} View installed skills`,
190
+ ` ${pc.cyan("/remind")} Set a reminder (e.g. /remind 30m Review PR)`,
191
+ ` ${pc.cyan("/model")} Show current LLM model`,
192
+ ` ${pc.cyan("/clear")} Clear conversation history`,
193
+ ` ${pc.cyan("/quit")} Exit`
194
+ ].join("\n")
195
+ };
196
+ }
197
+ if (cmd === "/identity") {
198
+ const content = readEcosystemFile(
199
+ path3.join(home, ".acore", "core.md"),
200
+ "identity (acore)"
201
+ );
202
+ return { handled: true, output: content };
203
+ }
204
+ if (cmd === "/tools") {
205
+ const content = readEcosystemFile(
206
+ path3.join(home, ".akit", "kit.md"),
207
+ "tools (akit)"
208
+ );
209
+ return { handled: true, output: content };
210
+ }
211
+ if (cmd === "/workflows") {
212
+ const content = readEcosystemFile(
213
+ path3.join(home, ".aflow", "flow.md"),
214
+ "workflows (aflow)"
215
+ );
216
+ return { handled: true, output: content };
217
+ }
218
+ if (cmd === "/rules") {
219
+ const content = readEcosystemFile(
220
+ path3.join(home, ".arules", "rules.md"),
221
+ "guardrails (arules)"
222
+ );
223
+ return { handled: true, output: content };
224
+ }
225
+ if (cmd === "/skills") {
226
+ const content = readEcosystemFile(
227
+ path3.join(home, ".askill", "skills.md"),
228
+ "skills (askill)"
229
+ );
230
+ return { handled: true, output: content };
231
+ }
232
+ if (cmd === "/model") {
233
+ return {
234
+ handled: true,
235
+ output: model ? `Model: ${pc.bold(model)}` : "Model: unknown"
236
+ };
237
+ }
238
+ if (cmd === "/clear") {
239
+ return { handled: true, output: pc.dim("Conversation cleared."), clearHistory: true };
240
+ }
241
+ if (cmd.startsWith("/remind")) {
242
+ const parts = input.trim().split(/\s+/);
243
+ if (parts.length < 3) {
244
+ return {
245
+ handled: true,
246
+ output: "Usage: /remind <time> <message>\nExamples: /remind 30m Review PR, /remind 2h Deploy, /remind tomorrow Check metrics"
247
+ };
248
+ }
249
+ const timeStr = parts[1];
250
+ const message = parts.slice(2).join(" ");
251
+ return { handled: true, remind: { timeStr, message } };
252
+ }
253
+ if (cmd.startsWith("/")) {
254
+ return {
255
+ handled: true,
256
+ output: `Unknown command: ${cmd}. Type ${pc.cyan("/help")} for available commands.`
257
+ };
258
+ }
259
+ return { handled: false };
260
+ }
261
+
262
+ // src/reminders.ts
263
+ import pc2 from "picocolors";
264
+ var activeReminders = [];
265
+ function parseTime(timeStr) {
266
+ const match = timeStr.match(/^(\d+)(m|h)$/);
267
+ if (match) {
268
+ const value = parseInt(match[1]);
269
+ const unit = match[2];
270
+ return unit === "m" ? value * 60 * 1e3 : value * 60 * 60 * 1e3;
271
+ }
272
+ if (timeStr === "tomorrow") return 24 * 60 * 60 * 1e3;
273
+ return null;
274
+ }
275
+ function setReminder(timeStr, message) {
276
+ const ms = parseTime(timeStr);
277
+ if (!ms) return null;
278
+ const reminder = {
279
+ message,
280
+ dueAt: Date.now() + ms
281
+ };
282
+ reminder.timer = setTimeout(() => {
283
+ console.log(`
284
+ ${pc2.yellow("\u23F0")} ${pc2.bold("Reminder:")} ${message}`);
285
+ const idx = activeReminders.indexOf(reminder);
286
+ if (idx >= 0) activeReminders.splice(idx, 1);
287
+ }, ms);
288
+ activeReminders.push(reminder);
289
+ const mins = Math.round(ms / 6e4);
290
+ if (mins < 60) return `${mins} minutes`;
291
+ const hours = Math.round(mins / 60);
292
+ return `${hours} hour${hours > 1 ? "s" : ""}`;
293
+ }
294
+ function clearReminders() {
295
+ for (const r of activeReminders) {
296
+ if (r.timer) clearTimeout(r.timer);
297
+ }
298
+ activeReminders.length = 0;
299
+ }
300
+
301
+ // src/agent.ts
302
+ async function runAgent(client, systemPrompt, aiName, model) {
303
+ const messages = [];
304
+ const rl = readline.createInterface({
305
+ input: process.stdin,
306
+ output: process.stdout
307
+ });
308
+ rl.on("SIGINT", () => {
309
+ console.log(pc3.dim("\nGoodbye.\n"));
310
+ rl.close();
311
+ process.exit(0);
312
+ });
313
+ const prompt = () => {
314
+ return new Promise((resolve) => {
315
+ rl.question(pc3.green("\nYou > "), (answer) => {
316
+ resolve(answer);
317
+ });
318
+ });
319
+ };
320
+ console.log(
321
+ `
322
+ Type a message, ${pc3.dim("/help")} for commands, or ${pc3.dim("/quit")} to exit.
323
+ `
324
+ );
325
+ while (true) {
326
+ const input = await prompt();
327
+ if (!input.trim()) continue;
328
+ const cmdResult = handleCommand(input, model);
329
+ if (cmdResult.handled) {
330
+ if (cmdResult.quit) {
331
+ clearReminders();
332
+ console.log(pc3.dim("\nGoodbye.\n"));
333
+ rl.close();
334
+ return;
335
+ }
336
+ if (cmdResult.remind) {
337
+ const duration = setReminder(
338
+ cmdResult.remind.timeStr,
339
+ cmdResult.remind.message
340
+ );
341
+ if (duration) {
342
+ console.log(pc3.dim(`Reminder set for ${duration} from now.`));
343
+ } else {
344
+ console.log(
345
+ pc3.red("Invalid time format. Use: 5m, 30m, 1h, 2h, tomorrow")
346
+ );
347
+ }
348
+ continue;
349
+ }
350
+ if (cmdResult.output) {
351
+ console.log(cmdResult.output);
352
+ }
353
+ if (cmdResult.clearHistory) {
354
+ messages.length = 0;
355
+ }
356
+ continue;
357
+ }
358
+ messages.push({ role: "user", content: input });
359
+ process.stdout.write(pc3.cyan(`
360
+ ${aiName} > `));
361
+ try {
362
+ const response = await client.chat(systemPrompt, messages, (chunk) => {
363
+ if (chunk.type === "text" && chunk.text) {
364
+ process.stdout.write(chunk.text);
365
+ }
366
+ if (chunk.type === "done") {
367
+ process.stdout.write("\n");
368
+ }
369
+ });
370
+ messages.push(response);
371
+ } catch (error) {
372
+ const message = error instanceof Error ? error.message : "Unknown error occurred";
373
+ console.error(pc3.red(`
374
+ Error: ${message}`));
375
+ messages.pop();
376
+ }
377
+ }
378
+ }
379
+
380
+ // src/scheduler.ts
381
+ import fs4 from "fs";
382
+ import path4 from "path";
383
+ import os4 from "os";
384
+ var SCHEDULES_PATH = path4.join(os4.homedir(), ".aman-agent", "schedules.json");
385
+ function loadSchedules() {
386
+ if (!fs4.existsSync(SCHEDULES_PATH)) return [];
387
+ try {
388
+ return JSON.parse(fs4.readFileSync(SCHEDULES_PATH, "utf-8"));
389
+ } catch {
390
+ return [];
391
+ }
392
+ }
393
+ function saveSchedules(tasks) {
394
+ const dir = path4.dirname(SCHEDULES_PATH);
395
+ fs4.mkdirSync(dir, { recursive: true });
396
+ fs4.writeFileSync(
397
+ SCHEDULES_PATH,
398
+ JSON.stringify(tasks, null, 2) + "\n",
399
+ "utf-8"
400
+ );
401
+ }
402
+ function addSchedule(task) {
403
+ const tasks = loadSchedules();
404
+ const newTask = {
405
+ ...task,
406
+ id: Date.now().toString(36),
407
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
408
+ };
409
+ tasks.push(newTask);
410
+ saveSchedules(tasks);
411
+ return newTask;
412
+ }
413
+ function removeSchedule(id) {
414
+ const tasks = loadSchedules();
415
+ const filtered = tasks.filter((t) => t.id !== id);
416
+ if (filtered.length === tasks.length) return false;
417
+ saveSchedules(filtered);
418
+ return true;
419
+ }
420
+ function getDueTasks() {
421
+ const tasks = loadSchedules();
422
+ const now = /* @__PURE__ */ new Date();
423
+ return tasks.filter((task) => {
424
+ if (!task.lastRun) return true;
425
+ const lastRun = new Date(task.lastRun);
426
+ return isDue(task.schedule, lastRun, now);
427
+ });
428
+ }
429
+ function isDue(schedule, lastRun, now) {
430
+ const hoursSinceLastRun = (now.getTime() - lastRun.getTime()) / (1e3 * 60 * 60);
431
+ if (schedule.startsWith("every ")) {
432
+ const match = schedule.match(/every (\d+)h/);
433
+ if (match) return hoursSinceLastRun >= parseInt(match[1]);
434
+ }
435
+ if (schedule === "daily" || schedule.startsWith("daily ")) {
436
+ return hoursSinceLastRun >= 20;
437
+ }
438
+ if (schedule === "weekdays" || schedule.startsWith("weekdays ")) {
439
+ const day = now.getDay();
440
+ return day >= 1 && day <= 5 && hoursSinceLastRun >= 20;
441
+ }
442
+ if (schedule.startsWith("weekly")) {
443
+ return hoursSinceLastRun >= 144;
444
+ }
445
+ return false;
446
+ }
447
+
448
+ // src/notifications.ts
449
+ import fs5 from "fs";
450
+ import path5 from "path";
451
+ import os5 from "os";
452
+ import pc4 from "picocolors";
453
+ function checkNotifications() {
454
+ const notifications = [];
455
+ const dueTasks = getDueTasks();
456
+ for (const task of dueTasks) {
457
+ notifications.push({
458
+ type: "schedule",
459
+ message: `${task.name} (${task.schedule})`
460
+ });
461
+ }
462
+ const evalPath = path5.join(os5.homedir(), ".aeval", "eval.md");
463
+ if (fs5.existsSync(evalPath)) {
464
+ const content = fs5.readFileSync(evalPath, "utf-8");
465
+ const dateMatch = content.match(/- Last updated: (.+)$/m);
466
+ if (dateMatch) {
467
+ const lastDate = new Date(dateMatch[1]);
468
+ const daysSince = (Date.now() - lastDate.getTime()) / (1e3 * 60 * 60 * 24);
469
+ if (daysSince > 3) {
470
+ notifications.push({
471
+ type: "eval",
472
+ message: `No session logged in ${Math.floor(daysSince)} days \u2014 run /eval to log one`
473
+ });
474
+ }
475
+ }
476
+ }
477
+ return notifications;
478
+ }
479
+ function displayNotifications(notifications) {
480
+ if (notifications.length === 0) return;
481
+ console.log(
482
+ pc4.yellow(
483
+ `
484
+ \u26A0 ${notifications.length} notification${notifications.length > 1 ? "s" : ""}:`
485
+ )
486
+ );
487
+ for (const n of notifications) {
488
+ console.log(` - ${n.message}`);
489
+ }
490
+ console.log("");
491
+ }
492
+
493
+ // src/index.ts
494
+ import fs6 from "fs";
495
+ import path6 from "path";
496
+ import os6 from "os";
497
+ var program = new Command();
498
+ program.name("aman-agent").description("Your AI companion, running locally").version("0.1.0").option("--model <model>", "Override LLM model").action(async (options) => {
499
+ p.intro(pc5.bold("aman agent") + pc5.dim(" \u2014 starting your AI companion"));
500
+ let config = loadConfig();
501
+ if (!config) {
502
+ p.log.info("First-time setup \u2014 configure your LLM connection.");
503
+ const provider = await p.select({
504
+ message: "LLM provider",
505
+ options: [
506
+ {
507
+ value: "anthropic",
508
+ label: "Claude (Anthropic)",
509
+ hint: "recommended"
510
+ },
511
+ { value: "openai", label: "GPT (OpenAI)" }
512
+ ],
513
+ initialValue: "anthropic"
514
+ });
515
+ if (p.isCancel(provider)) process.exit(0);
516
+ const apiKey = await p.text({
517
+ message: "API key",
518
+ validate: (v) => v.length === 0 ? "API key is required" : void 0
519
+ });
520
+ if (p.isCancel(apiKey)) process.exit(0);
521
+ const defaultModel = provider === "anthropic" ? "claude-sonnet-4-5-20250514" : "gpt-4o";
522
+ config = { provider, apiKey, model: defaultModel };
523
+ saveConfig(config);
524
+ p.log.success("Config saved to ~/.aman-agent/config.json");
525
+ }
526
+ const model = options.model || config.model;
527
+ const { prompt: systemPrompt, layers } = assembleSystemPrompt();
528
+ if (layers.length === 0) {
529
+ p.log.warning(
530
+ "No ecosystem configured. Run " + pc5.bold("npx @aman_asmuei/aman") + " first."
531
+ );
532
+ p.log.info("Starting with empty system prompt.");
533
+ } else {
534
+ p.log.success(`Loaded: ${layers.join(", ")}`);
535
+ }
536
+ p.log.info(`Model: ${pc5.dim(model)}`);
537
+ const corePath = path6.join(os6.homedir(), ".acore", "core.md");
538
+ let aiName = "Assistant";
539
+ if (fs6.existsSync(corePath)) {
540
+ const content = fs6.readFileSync(corePath, "utf-8");
541
+ const match = content.match(/^# (.+)$/m);
542
+ if (match) aiName = match[1];
543
+ }
544
+ p.log.success(`${pc5.bold(aiName)} is ready.`);
545
+ const notifications = checkNotifications();
546
+ displayNotifications(notifications);
547
+ const client = config.provider === "anthropic" ? createAnthropicClient(config.apiKey, model) : createOpenAIClient(config.apiKey, model);
548
+ await runAgent(client, systemPrompt, aiName, model);
549
+ });
550
+ program.command("schedule").description("Manage scheduled tasks").argument("[action]", "add, list, or remove").argument("[id]", "task ID (for remove)").action(async (action, id) => {
551
+ if (!action || action === "list") {
552
+ const tasks = loadSchedules();
553
+ if (tasks.length === 0) {
554
+ console.log(pc5.dim("No scheduled tasks."));
555
+ return;
556
+ }
557
+ console.log(pc5.bold("Scheduled tasks:\n"));
558
+ for (const task of tasks) {
559
+ const lastRun = task.lastRun ? pc5.dim(` (last run: ${new Date(task.lastRun).toLocaleString()})`) : pc5.dim(" (never run)");
560
+ console.log(
561
+ ` ${pc5.cyan(task.id)} ${task.name} ${pc5.dim(task.schedule)} [${task.mode}]${lastRun}`
562
+ );
563
+ }
564
+ return;
565
+ }
566
+ if (action === "add") {
567
+ const name = await p.text({
568
+ message: "Task name?",
569
+ validate: (v) => v.length === 0 ? "Name is required" : void 0
570
+ });
571
+ if (p.isCancel(name)) return;
572
+ const schedule = await p.select({
573
+ message: "Schedule?",
574
+ options: [
575
+ { value: "daily 9am", label: "Daily at 9am" },
576
+ { value: "weekdays 9am", label: "Weekdays at 9am" },
577
+ { value: "weekly friday 4pm", label: "Weekly Friday 4pm" },
578
+ { value: "every 2h", label: "Every 2 hours" },
579
+ { value: "every 4h", label: "Every 4 hours" }
580
+ ]
581
+ });
582
+ if (p.isCancel(schedule)) return;
583
+ const actionType = await p.select({
584
+ message: "What should happen?",
585
+ options: [
586
+ { value: "notify", label: "Show notification" },
587
+ { value: "auto-run", label: "Run automatically" }
588
+ ]
589
+ });
590
+ if (p.isCancel(actionType)) return;
591
+ let taskAction = "notify";
592
+ if (actionType === "auto-run") {
593
+ const cmd = await p.text({
594
+ message: "Command to run?",
595
+ placeholder: "e.g. run:daily-standup",
596
+ validate: (v) => v.length === 0 ? "Command is required" : void 0
597
+ });
598
+ if (p.isCancel(cmd)) return;
599
+ taskAction = cmd;
600
+ }
601
+ const task = addSchedule({
602
+ name,
603
+ schedule,
604
+ action: taskAction,
605
+ mode: actionType
606
+ });
607
+ console.log(
608
+ pc5.green(`
609
+ Scheduled task created: ${pc5.bold(task.name)} (${task.id})`)
610
+ );
611
+ return;
612
+ }
613
+ if (action === "remove") {
614
+ if (!id) {
615
+ console.log(pc5.red("Usage: aman-agent schedule remove <id>"));
616
+ return;
617
+ }
618
+ const removed = removeSchedule(id);
619
+ if (removed) {
620
+ console.log(pc5.green(`Task ${id} removed.`));
621
+ } else {
622
+ console.log(pc5.red(`Task ${id} not found.`));
623
+ }
624
+ return;
625
+ }
626
+ console.log(
627
+ pc5.red(`Unknown action: ${action}. Use add, list, or remove.`)
628
+ );
629
+ });
630
+ program.parse();
631
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/prompt.ts","../src/llm/anthropic.ts","../src/llm/openai.ts","../src/agent.ts","../src/commands.ts","../src/reminders.ts","../src/scheduler.ts","../src/notifications.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { loadConfig, saveConfig } from \"./config.js\";\nimport { assembleSystemPrompt } from \"./prompt.js\";\nimport { createAnthropicClient } from \"./llm/anthropic.js\";\nimport { createOpenAIClient } from \"./llm/openai.js\";\nimport { runAgent } from \"./agent.js\";\nimport {\n loadSchedules,\n addSchedule,\n removeSchedule,\n} from \"./scheduler.js\";\nimport {\n checkNotifications,\n displayNotifications,\n} from \"./notifications.js\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\ndeclare const __VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name(\"aman-agent\")\n .description(\"Your AI companion, running locally\")\n .version(__VERSION__)\n .option(\"--model <model>\", \"Override LLM model\")\n .action(async (options) => {\n p.intro(pc.bold(\"aman agent\") + pc.dim(\" — starting your AI companion\"));\n\n // Setup config if needed\n let config = loadConfig();\n if (!config) {\n p.log.info(\"First-time setup — configure your LLM connection.\");\n\n const provider = (await p.select({\n message: \"LLM provider\",\n options: [\n {\n value: \"anthropic\",\n label: \"Claude (Anthropic)\",\n hint: \"recommended\",\n },\n { value: \"openai\", label: \"GPT (OpenAI)\" },\n ],\n initialValue: \"anthropic\",\n })) as \"anthropic\" | \"openai\";\n if (p.isCancel(provider)) process.exit(0);\n\n const apiKey = (await p.text({\n message: \"API key\",\n validate: (v) =>\n v.length === 0 ? \"API key is required\" : undefined,\n })) as string;\n if (p.isCancel(apiKey)) process.exit(0);\n\n const defaultModel =\n provider === \"anthropic\" ? \"claude-sonnet-4-5-20250514\" : \"gpt-4o\";\n\n config = { provider, apiKey, model: defaultModel };\n saveConfig(config);\n p.log.success(\"Config saved to ~/.aman-agent/config.json\");\n }\n\n // Override model if specified\n const model = options.model || config.model;\n\n // Assemble system prompt from ecosystem\n const { prompt: systemPrompt, layers } = assembleSystemPrompt();\n\n if (layers.length === 0) {\n p.log.warning(\n \"No ecosystem configured. Run \" +\n pc.bold(\"npx @aman_asmuei/aman\") +\n \" first.\",\n );\n p.log.info(\"Starting with empty system prompt.\");\n } else {\n p.log.success(`Loaded: ${layers.join(\", \")}`);\n }\n\n p.log.info(`Model: ${pc.dim(model)}`);\n\n // Extract AI name from core.md\n const corePath = path.join(os.homedir(), \".acore\", \"core.md\");\n let aiName = \"Assistant\";\n if (fs.existsSync(corePath)) {\n const content = fs.readFileSync(corePath, \"utf-8\");\n const match = content.match(/^# (.+)$/m);\n if (match) aiName = match[1];\n }\n\n p.log.success(`${pc.bold(aiName)} is ready.`);\n\n // Session-start notifications\n const notifications = checkNotifications();\n displayNotifications(notifications);\n\n // Create LLM client\n const client =\n config.provider === \"anthropic\"\n ? createAnthropicClient(config.apiKey, model)\n : createOpenAIClient(config.apiKey, model);\n\n // Run the agent\n await runAgent(client, systemPrompt, aiName, model);\n });\n\nprogram\n .command(\"schedule\")\n .description(\"Manage scheduled tasks\")\n .argument(\"[action]\", \"add, list, or remove\")\n .argument(\"[id]\", \"task ID (for remove)\")\n .action(async (action?: string, id?: string) => {\n if (!action || action === \"list\") {\n const tasks = loadSchedules();\n if (tasks.length === 0) {\n console.log(pc.dim(\"No scheduled tasks.\"));\n return;\n }\n console.log(pc.bold(\"Scheduled tasks:\\n\"));\n for (const task of tasks) {\n const lastRun = task.lastRun\n ? pc.dim(` (last run: ${new Date(task.lastRun).toLocaleString()})`)\n : pc.dim(\" (never run)\");\n console.log(\n ` ${pc.cyan(task.id)} ${task.name} ${pc.dim(task.schedule)} [${task.mode}]${lastRun}`,\n );\n }\n return;\n }\n\n if (action === \"add\") {\n const name = (await p.text({\n message: \"Task name?\",\n validate: (v) => (v.length === 0 ? \"Name is required\" : undefined),\n })) as string;\n if (p.isCancel(name)) return;\n\n const schedule = (await p.select({\n message: \"Schedule?\",\n options: [\n { value: \"daily 9am\", label: \"Daily at 9am\" },\n { value: \"weekdays 9am\", label: \"Weekdays at 9am\" },\n { value: \"weekly friday 4pm\", label: \"Weekly Friday 4pm\" },\n { value: \"every 2h\", label: \"Every 2 hours\" },\n { value: \"every 4h\", label: \"Every 4 hours\" },\n ],\n })) as string;\n if (p.isCancel(schedule)) return;\n\n const actionType = (await p.select({\n message: \"What should happen?\",\n options: [\n { value: \"notify\", label: \"Show notification\" },\n { value: \"auto-run\", label: \"Run automatically\" },\n ],\n })) as \"notify\" | \"auto-run\";\n if (p.isCancel(actionType)) return;\n\n let taskAction = \"notify\";\n if (actionType === \"auto-run\") {\n const cmd = (await p.text({\n message: \"Command to run?\",\n placeholder: \"e.g. run:daily-standup\",\n validate: (v) =>\n v.length === 0 ? \"Command is required\" : undefined,\n })) as string;\n if (p.isCancel(cmd)) return;\n taskAction = cmd;\n }\n\n const task = addSchedule({\n name,\n schedule,\n action: taskAction,\n mode: actionType,\n });\n console.log(\n pc.green(`\\nScheduled task created: ${pc.bold(task.name)} (${task.id})`),\n );\n return;\n }\n\n if (action === \"remove\") {\n if (!id) {\n console.log(pc.red(\"Usage: aman-agent schedule remove <id>\"));\n return;\n }\n const removed = removeSchedule(id);\n if (removed) {\n console.log(pc.green(`Task ${id} removed.`));\n } else {\n console.log(pc.red(`Task ${id} not found.`));\n }\n return;\n }\n\n console.log(\n pc.red(`Unknown action: ${action}. Use add, list, or remove.`),\n );\n });\n\nprogram.parse();\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nexport interface AgentConfig {\n provider: \"anthropic\" | \"openai\";\n apiKey: string;\n model: string;\n}\n\nconst CONFIG_DIR = path.join(os.homedir(), \".aman-agent\");\nconst CONFIG_PATH = path.join(CONFIG_DIR, \"config.json\");\n\nexport function loadConfig(): AgentConfig | null {\n if (!fs.existsSync(CONFIG_PATH)) return null;\n try {\n return JSON.parse(fs.readFileSync(CONFIG_PATH, \"utf-8\"));\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: AgentConfig): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n fs.writeFileSync(\n CONFIG_PATH,\n JSON.stringify(config, null, 2) + \"\\n\",\n \"utf-8\",\n );\n}\n\nexport function configExists(): boolean {\n return fs.existsSync(CONFIG_PATH);\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nexport function assembleSystemPrompt(): { prompt: string; layers: string[] } {\n const home = os.homedir();\n const layers: string[] = [];\n const parts: string[] = [];\n\n // Identity (acore)\n const corePath = path.join(home, \".acore\", \"core.md\");\n if (fs.existsSync(corePath)) {\n parts.push(fs.readFileSync(corePath, \"utf-8\").trim());\n layers.push(\"identity\");\n }\n\n // Project context\n const contextPath = path.join(process.cwd(), \".acore\", \"context.md\");\n if (fs.existsSync(contextPath)) {\n parts.push(fs.readFileSync(contextPath, \"utf-8\").trim());\n }\n\n // Tools (akit)\n const kitPath = path.join(home, \".akit\", \"kit.md\");\n if (fs.existsSync(kitPath)) {\n parts.push(fs.readFileSync(kitPath, \"utf-8\").trim());\n layers.push(\"tools\");\n }\n\n // Workflows (aflow)\n const flowPath = path.join(home, \".aflow\", \"flow.md\");\n if (fs.existsSync(flowPath)) {\n parts.push(fs.readFileSync(flowPath, \"utf-8\").trim());\n layers.push(\"workflows\");\n }\n\n // Guardrails (arules)\n const rulesPath = path.join(home, \".arules\", \"rules.md\");\n if (fs.existsSync(rulesPath)) {\n parts.push(fs.readFileSync(rulesPath, \"utf-8\").trim());\n layers.push(\"guardrails\");\n }\n\n // Skills (askill)\n const skillsPath = path.join(home, \".askill\", \"skills.md\");\n if (fs.existsSync(skillsPath)) {\n parts.push(fs.readFileSync(skillsPath, \"utf-8\").trim());\n layers.push(\"skills\");\n }\n\n return {\n prompt: parts.join(\"\\n\\n---\\n\\n\"),\n layers,\n };\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport type { LLMClient, Message, StreamChunk } from \"./types.js\";\n\nexport function createAnthropicClient(\n apiKey: string,\n model: string,\n): LLMClient {\n const client = new Anthropic({ apiKey });\n\n return {\n async chat(systemPrompt, messages, onChunk) {\n let fullText = \"\";\n\n try {\n const stream = await client.messages.create({\n model,\n max_tokens: 8192,\n system: systemPrompt,\n messages: messages.map((m) => ({\n role: m.role,\n content: m.content,\n })),\n stream: true,\n });\n\n for await (const event of stream) {\n if (\n event.type === \"content_block_delta\" &&\n event.delta.type === \"text_delta\"\n ) {\n const text = event.delta.text;\n fullText += text;\n onChunk({ type: \"text\", text });\n }\n }\n } catch (error) {\n if (error instanceof Anthropic.AuthenticationError) {\n throw new Error(\n \"Invalid API key. Run with --model flag or delete ~/.aman-agent/config.json to reconfigure.\",\n );\n }\n if (error instanceof Anthropic.RateLimitError) {\n throw new Error(\"Rate limited by Anthropic. Please wait and retry.\");\n }\n throw error;\n }\n\n onChunk({ type: \"done\" });\n return { role: \"assistant\", content: fullText };\n },\n };\n}\n","import OpenAI from \"openai\";\nimport type { LLMClient, Message, StreamChunk } from \"./types.js\";\n\nexport function createOpenAIClient(apiKey: string, model: string): LLMClient {\n const client = new OpenAI({ apiKey });\n\n return {\n async chat(systemPrompt, messages, onChunk) {\n let fullText = \"\";\n\n try {\n const stream = await client.chat.completions.create({\n model,\n max_tokens: 8192,\n messages: [\n { role: \"system\", content: systemPrompt },\n ...messages.map((m) => ({\n role: m.role as \"user\" | \"assistant\",\n content: m.content,\n })),\n ],\n stream: true,\n });\n\n for await (const chunk of stream) {\n const text = chunk.choices[0]?.delta?.content || \"\";\n if (text) {\n fullText += text;\n onChunk({ type: \"text\", text });\n }\n }\n } catch (error) {\n if (error instanceof OpenAI.AuthenticationError) {\n throw new Error(\n \"Invalid API key. Run with --model flag or delete ~/.aman-agent/config.json to reconfigure.\",\n );\n }\n if (error instanceof OpenAI.RateLimitError) {\n throw new Error(\"Rate limited by OpenAI. Please wait and retry.\");\n }\n throw error;\n }\n\n onChunk({ type: \"done\" });\n return { role: \"assistant\", content: fullText };\n },\n };\n}\n","import * as readline from \"node:readline\";\nimport pc from \"picocolors\";\nimport type { LLMClient, Message } from \"./llm/types.js\";\nimport { handleCommand } from \"./commands.js\";\nimport { setReminder, clearReminders } from \"./reminders.js\";\n\nexport async function runAgent(\n client: LLMClient,\n systemPrompt: string,\n aiName: string,\n model: string,\n): Promise<void> {\n const messages: Message[] = [];\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n // Handle Ctrl+C gracefully\n rl.on(\"SIGINT\", () => {\n console.log(pc.dim(\"\\nGoodbye.\\n\"));\n rl.close();\n process.exit(0);\n });\n\n const prompt = (): Promise<string> => {\n return new Promise<string>((resolve) => {\n rl.question(pc.green(\"\\nYou > \"), (answer) => {\n resolve(answer);\n });\n });\n };\n\n console.log(\n `\\nType a message, ${pc.dim(\"/help\")} for commands, or ${pc.dim(\"/quit\")} to exit.\\n`,\n );\n\n while (true) {\n const input = await prompt();\n if (!input.trim()) continue;\n\n // Handle slash commands\n const cmdResult = handleCommand(input, model);\n if (cmdResult.handled) {\n if (cmdResult.quit) {\n clearReminders();\n console.log(pc.dim(\"\\nGoodbye.\\n\"));\n rl.close();\n return;\n }\n if (cmdResult.remind) {\n const duration = setReminder(\n cmdResult.remind.timeStr,\n cmdResult.remind.message,\n );\n if (duration) {\n console.log(pc.dim(`Reminder set for ${duration} from now.`));\n } else {\n console.log(\n pc.red(\"Invalid time format. Use: 5m, 30m, 1h, 2h, tomorrow\"),\n );\n }\n continue;\n }\n if (cmdResult.output) {\n console.log(cmdResult.output);\n }\n if (cmdResult.clearHistory) {\n messages.length = 0;\n }\n continue;\n }\n\n // Send to LLM\n messages.push({ role: \"user\", content: input });\n\n process.stdout.write(pc.cyan(`\\n${aiName} > `));\n\n try {\n const response = await client.chat(systemPrompt, messages, (chunk) => {\n if (chunk.type === \"text\" && chunk.text) {\n process.stdout.write(chunk.text);\n }\n if (chunk.type === \"done\") {\n process.stdout.write(\"\\n\");\n }\n });\n\n messages.push(response);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Unknown error occurred\";\n console.error(pc.red(`\\nError: ${message}`));\n // Remove the user message that failed\n messages.pop();\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport pc from \"picocolors\";\n\nexport interface CommandResult {\n handled: boolean;\n output?: string;\n quit?: boolean;\n clearHistory?: boolean;\n remind?: { timeStr: string; message: string };\n}\n\nfunction readEcosystemFile(filePath: string, label: string): string {\n if (!fs.existsSync(filePath)) {\n return pc.dim(`No ${label} file found at ${filePath}`);\n }\n return fs.readFileSync(filePath, \"utf-8\").trim();\n}\n\nexport function handleCommand(input: string, model?: string): CommandResult {\n const cmd = input.trim().toLowerCase();\n const home = os.homedir();\n\n if (cmd === \"/quit\" || cmd === \"/exit\" || cmd === \"/q\") {\n return { handled: true, quit: true };\n }\n\n if (cmd === \"/help\") {\n return {\n handled: true,\n output: [\n pc.bold(\"Commands:\"),\n ` ${pc.cyan(\"/help\")} Show this help`,\n ` ${pc.cyan(\"/identity\")} View your AI identity`,\n ` ${pc.cyan(\"/tools\")} View installed tools`,\n ` ${pc.cyan(\"/workflows\")} View defined workflows`,\n ` ${pc.cyan(\"/rules\")} View guardrails`,\n ` ${pc.cyan(\"/skills\")} View installed skills`,\n ` ${pc.cyan(\"/remind\")} Set a reminder (e.g. /remind 30m Review PR)`,\n ` ${pc.cyan(\"/model\")} Show current LLM model`,\n ` ${pc.cyan(\"/clear\")} Clear conversation history`,\n ` ${pc.cyan(\"/quit\")} Exit`,\n ].join(\"\\n\"),\n };\n }\n\n if (cmd === \"/identity\") {\n const content = readEcosystemFile(\n path.join(home, \".acore\", \"core.md\"),\n \"identity (acore)\",\n );\n return { handled: true, output: content };\n }\n\n if (cmd === \"/tools\") {\n const content = readEcosystemFile(\n path.join(home, \".akit\", \"kit.md\"),\n \"tools (akit)\",\n );\n return { handled: true, output: content };\n }\n\n if (cmd === \"/workflows\") {\n const content = readEcosystemFile(\n path.join(home, \".aflow\", \"flow.md\"),\n \"workflows (aflow)\",\n );\n return { handled: true, output: content };\n }\n\n if (cmd === \"/rules\") {\n const content = readEcosystemFile(\n path.join(home, \".arules\", \"rules.md\"),\n \"guardrails (arules)\",\n );\n return { handled: true, output: content };\n }\n\n if (cmd === \"/skills\") {\n const content = readEcosystemFile(\n path.join(home, \".askill\", \"skills.md\"),\n \"skills (askill)\",\n );\n return { handled: true, output: content };\n }\n\n if (cmd === \"/model\") {\n return {\n handled: true,\n output: model ? `Model: ${pc.bold(model)}` : \"Model: unknown\",\n };\n }\n\n if (cmd === \"/clear\") {\n return { handled: true, output: pc.dim(\"Conversation cleared.\"), clearHistory: true };\n }\n\n if (cmd.startsWith(\"/remind\")) {\n const parts = input.trim().split(/\\s+/);\n if (parts.length < 3) {\n return {\n handled: true,\n output:\n \"Usage: /remind <time> <message>\\nExamples: /remind 30m Review PR, /remind 2h Deploy, /remind tomorrow Check metrics\",\n };\n }\n const timeStr = parts[1];\n const message = parts.slice(2).join(\" \");\n return { handled: true, remind: { timeStr, message } };\n }\n\n if (cmd.startsWith(\"/\")) {\n return {\n handled: true,\n output: `Unknown command: ${cmd}. Type ${pc.cyan(\"/help\")} for available commands.`,\n };\n }\n\n return { handled: false };\n}\n","import pc from \"picocolors\";\n\ninterface Reminder {\n message: string;\n dueAt: number;\n timer?: ReturnType<typeof setTimeout>;\n}\n\nconst activeReminders: Reminder[] = [];\n\nexport function parseTime(timeStr: string): number | null {\n const match = timeStr.match(/^(\\d+)(m|h)$/);\n if (match) {\n const value = parseInt(match[1]);\n const unit = match[2];\n return unit === \"m\" ? value * 60 * 1000 : value * 60 * 60 * 1000;\n }\n if (timeStr === \"tomorrow\") return 24 * 60 * 60 * 1000;\n return null;\n}\n\nexport function setReminder(timeStr: string, message: string): string | null {\n const ms = parseTime(timeStr);\n if (!ms) return null;\n\n const reminder: Reminder = {\n message,\n dueAt: Date.now() + ms,\n };\n\n reminder.timer = setTimeout(() => {\n console.log(`\\n${pc.yellow(\"\\u23f0\")} ${pc.bold(\"Reminder:\")} ${message}`);\n const idx = activeReminders.indexOf(reminder);\n if (idx >= 0) activeReminders.splice(idx, 1);\n }, ms);\n\n activeReminders.push(reminder);\n\n const mins = Math.round(ms / 60000);\n if (mins < 60) return `${mins} minutes`;\n const hours = Math.round(mins / 60);\n return `${hours} hour${hours > 1 ? \"s\" : \"\"}`;\n}\n\nexport function clearReminders(): void {\n for (const r of activeReminders) {\n if (r.timer) clearTimeout(r.timer);\n }\n activeReminders.length = 0;\n}\n\nexport function getActiveCount(): number {\n return activeReminders.length;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nconst SCHEDULES_PATH = path.join(os.homedir(), \".aman-agent\", \"schedules.json\");\n\nexport interface ScheduledTask {\n id: string;\n name: string;\n schedule: string;\n action: string;\n mode: \"notify\" | \"auto-run\";\n createdAt: string;\n lastRun?: string;\n}\n\nexport function loadSchedules(): ScheduledTask[] {\n if (!fs.existsSync(SCHEDULES_PATH)) return [];\n try {\n return JSON.parse(fs.readFileSync(SCHEDULES_PATH, \"utf-8\"));\n } catch {\n return [];\n }\n}\n\nexport function saveSchedules(tasks: ScheduledTask[]): void {\n const dir = path.dirname(SCHEDULES_PATH);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(\n SCHEDULES_PATH,\n JSON.stringify(tasks, null, 2) + \"\\n\",\n \"utf-8\",\n );\n}\n\nexport function addSchedule(\n task: Omit<ScheduledTask, \"id\" | \"createdAt\">,\n): ScheduledTask {\n const tasks = loadSchedules();\n const newTask: ScheduledTask = {\n ...task,\n id: Date.now().toString(36),\n createdAt: new Date().toISOString(),\n };\n tasks.push(newTask);\n saveSchedules(tasks);\n return newTask;\n}\n\nexport function removeSchedule(id: string): boolean {\n const tasks = loadSchedules();\n const filtered = tasks.filter((t) => t.id !== id);\n if (filtered.length === tasks.length) return false;\n saveSchedules(filtered);\n return true;\n}\n\nexport function getDueTasks(): ScheduledTask[] {\n const tasks = loadSchedules();\n const now = new Date();\n return tasks.filter((task) => {\n if (!task.lastRun) return true;\n const lastRun = new Date(task.lastRun);\n return isDue(task.schedule, lastRun, now);\n });\n}\n\nexport function isDue(schedule: string, lastRun: Date, now: Date): boolean {\n const hoursSinceLastRun =\n (now.getTime() - lastRun.getTime()) / (1000 * 60 * 60);\n\n if (schedule.startsWith(\"every \")) {\n const match = schedule.match(/every (\\d+)h/);\n if (match) return hoursSinceLastRun >= parseInt(match[1]);\n }\n if (schedule === \"daily\" || schedule.startsWith(\"daily \")) {\n return hoursSinceLastRun >= 20;\n }\n if (schedule === \"weekdays\" || schedule.startsWith(\"weekdays \")) {\n const day = now.getDay();\n return day >= 1 && day <= 5 && hoursSinceLastRun >= 20;\n }\n if (schedule.startsWith(\"weekly\")) {\n return hoursSinceLastRun >= 144;\n }\n return false;\n}\n\nexport function markRun(id: string): void {\n const tasks = loadSchedules();\n const task = tasks.find((t) => t.id === id);\n if (task) {\n task.lastRun = new Date().toISOString();\n saveSchedules(tasks);\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport pc from \"picocolors\";\nimport { getDueTasks } from \"./scheduler.js\";\n\nexport interface Notification {\n type: \"schedule\" | \"eval\" | \"health\";\n message: string;\n}\n\nexport function checkNotifications(): Notification[] {\n const notifications: Notification[] = [];\n\n // Check due scheduled tasks\n const dueTasks = getDueTasks();\n for (const task of dueTasks) {\n notifications.push({\n type: \"schedule\",\n message: `${task.name} (${task.schedule})`,\n });\n }\n\n // Check aeval — sessions not logged recently\n const evalPath = path.join(os.homedir(), \".aeval\", \"eval.md\");\n if (fs.existsSync(evalPath)) {\n const content = fs.readFileSync(evalPath, \"utf-8\");\n const dateMatch = content.match(/- Last updated: (.+)$/m);\n if (dateMatch) {\n const lastDate = new Date(dateMatch[1]);\n const daysSince =\n (Date.now() - lastDate.getTime()) / (1000 * 60 * 60 * 24);\n if (daysSince > 3) {\n notifications.push({\n type: \"eval\",\n message: `No session logged in ${Math.floor(daysSince)} days \\u2014 run /eval to log one`,\n });\n }\n }\n }\n\n return notifications;\n}\n\nexport function displayNotifications(notifications: Notification[]): void {\n if (notifications.length === 0) return;\n\n console.log(\n pc.yellow(\n `\\n\\u26a0 ${notifications.length} notification${notifications.length > 1 ? \"s\" : \"\"}:`,\n ),\n );\n for (const n of notifications) {\n console.log(` - ${n.message}`);\n }\n console.log(\"\");\n}\n"],"mappings":"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","names":["pc","fs","path","os","text","text","pc","fs","path","os","pc","pc","fs","path","os","fs","path","os","pc","path","os","fs","pc","fs","path","os","pc"]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@aman_asmuei/aman-agent",
3
+ "version": "0.1.0",
4
+ "description": "Your AI companion, running locally — powered by the aman ecosystem",
5
+ "type": "module",
6
+ "bin": {
7
+ "aman-agent": "./bin/aman-agent.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "files": [
11
+ "dist",
12
+ "bin"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsup",
16
+ "dev": "tsup --watch",
17
+ "lint": "tsc --noEmit",
18
+ "test": "vitest run",
19
+ "test:watch": "vitest",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "dependencies": {
23
+ "@anthropic-ai/sdk": "^0.39.0",
24
+ "@clack/prompts": "^0.9.1",
25
+ "commander": "^13.1.0",
26
+ "openai": "^4.80.0",
27
+ "picocolors": "^1.1.1"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.0.0",
31
+ "tsup": "^8.4.0",
32
+ "typescript": "^5.7.0",
33
+ "vitest": "^4.1.0"
34
+ },
35
+ "keywords": [
36
+ "ai",
37
+ "agent",
38
+ "companion",
39
+ "aman",
40
+ "llm",
41
+ "claude",
42
+ "openai"
43
+ ],
44
+ "author": "Aman Asmuei",
45
+ "license": "MIT",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/amanasmuei/aman-agent.git"
49
+ }
50
+ }