kern-ai 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/README.md +111 -0
- package/dist/app.d.ts +2 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +34 -0
- package/dist/app.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +48 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +2 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +187 -0
- package/dist/init.js.map +1 -0
- package/dist/interfaces/cli.d.ts +14 -0
- package/dist/interfaces/cli.d.ts.map +1 -0
- package/dist/interfaces/cli.js +142 -0
- package/dist/interfaces/cli.js.map +1 -0
- package/dist/interfaces/telegram.d.ts +10 -0
- package/dist/interfaces/telegram.d.ts.map +1 -0
- package/dist/interfaces/telegram.js +55 -0
- package/dist/interfaces/telegram.js.map +1 -0
- package/dist/interfaces/types.d.ts +17 -0
- package/dist/interfaces/types.d.ts.map +1 -0
- package/dist/interfaces/types.js +2 -0
- package/dist/interfaces/types.js.map +1 -0
- package/dist/runtime.d.ts +22 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +99 -0
- package/dist/runtime.js.map +1 -0
- package/dist/session.d.ts +21 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +102 -0
- package/dist/session.js.map +1 -0
- package/dist/tools/bash.d.ts +5 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +30 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit.d.ts +7 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +37 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/glob.d.ts +5 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +29 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.d.ts +6 -0
- package/dist/tools/grep.d.ts.map +1 -0
- package/dist/tools/grep.js +38 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.d.ts +32 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +15 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/read.d.ts +6 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +36 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/write.d.ts +5 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +22 -0
- package/dist/tools/write.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# kern
|
|
2
|
+
|
|
3
|
+
Simple agent runtime. Give any AI agent persistent memory and a Telegram interface.
|
|
4
|
+
|
|
5
|
+
kern pairs with [agent-kernel](https://github.com/oguzbilgic/agent-kernel) — the kernel defines how an agent remembers, kern runs it.
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx kern init my-agent
|
|
11
|
+
cd my-agent
|
|
12
|
+
npx kern
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The init wizard asks for a provider, API key, and model — then scaffolds an agent with persistent memory.
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
- **Runs an AI agent** with tools (bash, file read/write/edit, glob, grep)
|
|
20
|
+
- **Persists conversation** as JSONL — sessions resume where they left off
|
|
21
|
+
- **Streams responses** to the terminal with a live TUI
|
|
22
|
+
- **Reads AGENTS.md** as system prompt — the agent-kernel pattern for stateful agents
|
|
23
|
+
- **Connects to Telegram** (optional) — message your agent from anywhere
|
|
24
|
+
|
|
25
|
+
## How it works
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
You (CLI or Telegram)
|
|
29
|
+
→ kern runtime
|
|
30
|
+
→ Vercel AI SDK (model-agnostic)
|
|
31
|
+
→ tools execute (bash, read, write, edit, glob, grep)
|
|
32
|
+
→ response streams back
|
|
33
|
+
→ conversation saved to .kern/sessions/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The agent's memory lives in the repo — AGENTS.md, IDENTITY.md, KNOWLEDGE.md, knowledge/, notes/. The agent reads and writes these files through tools. Everything is plain text and git-tracked.
|
|
37
|
+
|
|
38
|
+
## Project structure
|
|
39
|
+
|
|
40
|
+
After `kern init`, your agent directory looks like:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
my-agent/
|
|
44
|
+
AGENTS.md # agent kernel — how the agent behaves
|
|
45
|
+
IDENTITY.md # who the agent is
|
|
46
|
+
KNOWLEDGE.md # index of knowledge files
|
|
47
|
+
knowledge/ # mutable state files
|
|
48
|
+
notes/ # daily logs (append-only)
|
|
49
|
+
.kern/
|
|
50
|
+
config.json # model, provider, tools (committed)
|
|
51
|
+
.env # API keys, bot tokens (gitignored)
|
|
52
|
+
sessions/ # conversation history (gitignored)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
`.kern/config.json`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"model": "anthropic/claude-opus-4",
|
|
62
|
+
"provider": "openrouter",
|
|
63
|
+
"tools": ["bash", "read", "write", "edit", "glob", "grep"],
|
|
64
|
+
"maxSteps": 30
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`.kern/.env`:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
OPENROUTER_API_KEY=sk-or-...
|
|
72
|
+
TELEGRAM_BOT_TOKEN=...
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Providers
|
|
76
|
+
|
|
77
|
+
- **openrouter** — any model via OpenRouter (default)
|
|
78
|
+
- **anthropic** — direct Anthropic API
|
|
79
|
+
- **openai** — OpenAI / Azure
|
|
80
|
+
|
|
81
|
+
## CLI usage
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
kern init <name> # create a new agent
|
|
85
|
+
kern <dir> # run agent in directory
|
|
86
|
+
kern # run agent in current directory
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Telegram
|
|
90
|
+
|
|
91
|
+
Set `TELEGRAM_BOT_TOKEN` in `.kern/.env` and kern automatically connects via long polling. No public URL needed — works behind NAT.
|
|
92
|
+
|
|
93
|
+
Optional: restrict access with allowed user IDs in `.kern/config.json`:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"telegram": {
|
|
98
|
+
"allowedUsers": [123456789]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Built with
|
|
104
|
+
|
|
105
|
+
- [Vercel AI SDK](https://sdk.vercel.ai) — model-agnostic AI layer
|
|
106
|
+
- [grammY](https://grammy.dev) — Telegram bot framework
|
|
107
|
+
- [agent-kernel](https://github.com/oguzbilgic/agent-kernel) — the memory pattern
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT
|
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAMA,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkC9D"}
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Runtime } from "./runtime.js";
|
|
2
|
+
import { TelegramInterface } from "./interfaces/telegram.js";
|
|
3
|
+
import { CliInterface, dim, bold, cyan } from "./interfaces/cli.js";
|
|
4
|
+
import { loadConfig } from "./config.js";
|
|
5
|
+
export async function startApp(agentDir) {
|
|
6
|
+
const config = await loadConfig(agentDir);
|
|
7
|
+
const runtime = new Runtime(agentDir);
|
|
8
|
+
await runtime.init();
|
|
9
|
+
// Set working directory to agent dir so tools operate there
|
|
10
|
+
process.chdir(agentDir);
|
|
11
|
+
// Pick interface: Telegram if token set, otherwise CLI
|
|
12
|
+
let iface;
|
|
13
|
+
const telegramToken = process.env.TELEGRAM_BOT_TOKEN;
|
|
14
|
+
if (telegramToken) {
|
|
15
|
+
const allowedUsers = config.telegram?.allowedUsers || [];
|
|
16
|
+
iface = new TelegramInterface(telegramToken, allowedUsers);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
iface = new CliInterface();
|
|
20
|
+
}
|
|
21
|
+
const handler = async (msg, onEvent) => {
|
|
22
|
+
return runtime.handleMessage(msg.text, onEvent);
|
|
23
|
+
};
|
|
24
|
+
const w = (s) => process.stdout.write(s + "\n");
|
|
25
|
+
w("");
|
|
26
|
+
w(` ${bold("kern")} ${cyan(agentDir)}`);
|
|
27
|
+
w(` ${"model"} ${dim(config.provider + "/" + config.model)}`);
|
|
28
|
+
w(` ${"session"} ${dim(runtime.getSessionId() || "new")}`);
|
|
29
|
+
w(` ${"tools"} ${dim(config.tools.join(", "))}`);
|
|
30
|
+
w(` ${dim("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")}`);
|
|
31
|
+
w("");
|
|
32
|
+
await iface.start({ onMessage: handler, history: runtime.getMessages() });
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;IAErB,4DAA4D;IAC5D,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAExB,uDAAuD;IACvD,IAAI,KAAgB,CAAC;IACrB,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAErD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,EAAE,YAAY,IAAI,EAAE,CAAC;QACzD,KAAK,GAAG,IAAI,iBAAiB,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAC7D,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,IAAI,YAAY,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,OAAO,GAAmB,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACrD,OAAO,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC,CAAC;IAEF,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAExD,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,KAAK,OAAO,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,GAAG,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,KAAK,SAAS,KAAK,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,KAAK,OAAO,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,KAAK,GAAG,CAAC,kDAAkD,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,EAAE,CAAC,CAAC;IAEN,MAAM,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AAC5E,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface KernConfig {
|
|
2
|
+
model: string;
|
|
3
|
+
provider: string;
|
|
4
|
+
tools: string[];
|
|
5
|
+
maxSteps: number;
|
|
6
|
+
telegram?: {
|
|
7
|
+
allowedUsers?: number[];
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export declare function loadConfig(agentDir: string): Promise<KernConfig>;
|
|
11
|
+
export declare function loadSystemPrompt(agentDir: string): Promise<string>;
|
|
12
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE;QACT,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;CACH;AASD,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAoBtE;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBxE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { readFile } from "fs/promises";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { config as loadDotenv } from "dotenv";
|
|
5
|
+
const defaults = {
|
|
6
|
+
model: "claude-sonnet-4-20250514",
|
|
7
|
+
provider: "anthropic",
|
|
8
|
+
tools: ["bash", "read", "write", "edit", "glob", "grep"],
|
|
9
|
+
maxSteps: 30,
|
|
10
|
+
};
|
|
11
|
+
export async function loadConfig(agentDir) {
|
|
12
|
+
// Load .kern/.env
|
|
13
|
+
const envPath = join(agentDir, ".kern", ".env");
|
|
14
|
+
if (existsSync(envPath)) {
|
|
15
|
+
loadDotenv({ path: envPath });
|
|
16
|
+
}
|
|
17
|
+
// Load .kern/config.json
|
|
18
|
+
const configPath = join(agentDir, ".kern", "config.json");
|
|
19
|
+
if (!existsSync(configPath)) {
|
|
20
|
+
return defaults;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const raw = await readFile(configPath, "utf-8");
|
|
24
|
+
const userConfig = JSON.parse(raw);
|
|
25
|
+
return { ...defaults, ...userConfig };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return defaults;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function loadSystemPrompt(agentDir) {
|
|
32
|
+
const parts = [];
|
|
33
|
+
// Load AGENTS.md (kernel)
|
|
34
|
+
const agentsPath = join(agentDir, "AGENTS.md");
|
|
35
|
+
if (existsSync(agentsPath)) {
|
|
36
|
+
parts.push(await readFile(agentsPath, "utf-8"));
|
|
37
|
+
}
|
|
38
|
+
// Load IDENTITY.md
|
|
39
|
+
const identityPath = join(agentDir, "IDENTITY.md");
|
|
40
|
+
if (existsSync(identityPath)) {
|
|
41
|
+
parts.push(await readFile(identityPath, "utf-8"));
|
|
42
|
+
}
|
|
43
|
+
if (parts.length === 0) {
|
|
44
|
+
return "You are a helpful AI assistant.";
|
|
45
|
+
}
|
|
46
|
+
return parts.join("\n\n---\n\n");
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,QAAQ,CAAC;AAY9C,MAAM,QAAQ,GAAe;IAC3B,KAAK,EAAE,0BAA0B;IACjC,QAAQ,EAAE,WAAW;IACrB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IACxD,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,kBAAkB;IAClB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,yBAAyB;IACzB,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnC,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,UAAU,EAAE,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,0BAA0B;IAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC/C,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,mBAAmB;IACnB,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACnD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,iCAAiC,CAAC;IAC3C,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACnC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env -S node --no-deprecation
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { startApp } from "./app.js";
|
|
5
|
+
import { runInit } from "./init.js";
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
if (args[0] === "init") {
|
|
8
|
+
runInit(args[1]).catch((error) => {
|
|
9
|
+
console.error("Error:", error.message);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
// Determine agent directory
|
|
15
|
+
const agentDir = resolve(args[0] || ".");
|
|
16
|
+
if (!existsSync(agentDir)) {
|
|
17
|
+
console.error(`Directory not found: ${agentDir}`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
// Check for .kern/ or AGENTS.md to verify it's an agent dir
|
|
21
|
+
const hasKernDir = existsSync(resolve(agentDir, ".kern"));
|
|
22
|
+
const hasAgentsMd = existsSync(resolve(agentDir, "AGENTS.md"));
|
|
23
|
+
if (!hasKernDir && !hasAgentsMd) {
|
|
24
|
+
console.error(`Not an agent directory: ${agentDir}`);
|
|
25
|
+
console.error("Run 'kern init' to set up a new agent, or point to an existing one.");
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
startApp(agentDir).catch((error) => {
|
|
29
|
+
console.error("Fatal:", error.message);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;IACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QAC/B,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,CAAC;IACN,4BAA4B;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IAEzC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,4DAA4D;IAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC;IAE/D,IAAI,CAAC,UAAU,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,KAAK,CACX,qEAAqE,CACtE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,QAAQ,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACjC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAmCA,wBAAsB,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiL/D"}
|
package/dist/init.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
2
|
+
import { join, resolve } from "path";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { createInterface } from "readline";
|
|
5
|
+
const rl = createInterface({
|
|
6
|
+
input: process.stdin,
|
|
7
|
+
output: process.stdout,
|
|
8
|
+
});
|
|
9
|
+
function ask(question, defaultValue) {
|
|
10
|
+
const suffix = defaultValue ? ` (${defaultValue})` : "";
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
rl.question(` ${question}${suffix}: `, (answer) => {
|
|
13
|
+
resolve(answer.trim() || defaultValue || "");
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function print(text) {
|
|
18
|
+
console.log(text);
|
|
19
|
+
}
|
|
20
|
+
const MODEL_DEFAULTS = {
|
|
21
|
+
openrouter: "anthropic/claude-opus-4",
|
|
22
|
+
anthropic: "claude-opus-4-20250514",
|
|
23
|
+
openai: "gpt-4o",
|
|
24
|
+
};
|
|
25
|
+
const API_KEY_LABELS = {
|
|
26
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
27
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
28
|
+
openai: "OPENAI_API_KEY",
|
|
29
|
+
};
|
|
30
|
+
export async function runInit(targetArg) {
|
|
31
|
+
print("");
|
|
32
|
+
print(" kern init");
|
|
33
|
+
print(" ─────────");
|
|
34
|
+
print("");
|
|
35
|
+
// Agent name
|
|
36
|
+
const name = await ask("Agent name", targetArg);
|
|
37
|
+
if (!name) {
|
|
38
|
+
print(" Name is required.");
|
|
39
|
+
rl.close();
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
// Determine directory
|
|
43
|
+
const dir = resolve(targetArg || name);
|
|
44
|
+
if (existsSync(dir) && existsSync(join(dir, "AGENTS.md"))) {
|
|
45
|
+
print(` ${dir} already exists and has AGENTS.md. Skipping scaffold.`);
|
|
46
|
+
rl.close();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Provider
|
|
50
|
+
const provider = await ask("Provider", "openrouter");
|
|
51
|
+
// API key
|
|
52
|
+
const apiKeyLabel = API_KEY_LABELS[provider] || "API_KEY";
|
|
53
|
+
const apiKey = await ask(apiKeyLabel);
|
|
54
|
+
// Model
|
|
55
|
+
const defaultModel = MODEL_DEFAULTS[provider] || "anthropic/claude-opus-4";
|
|
56
|
+
const model = await ask("Model", defaultModel);
|
|
57
|
+
// Telegram bot token (optional)
|
|
58
|
+
const telegramToken = await ask("Telegram bot token (optional)");
|
|
59
|
+
// Allowed Telegram user IDs (optional)
|
|
60
|
+
let allowedUsers = [];
|
|
61
|
+
if (telegramToken) {
|
|
62
|
+
const usersStr = await ask("Allowed Telegram user IDs (comma-separated, optional)");
|
|
63
|
+
if (usersStr) {
|
|
64
|
+
allowedUsers = usersStr.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
rl.close();
|
|
68
|
+
print("");
|
|
69
|
+
print(` Creating ${dir}/...`);
|
|
70
|
+
// Create directories
|
|
71
|
+
await mkdir(dir, { recursive: true });
|
|
72
|
+
await mkdir(join(dir, "knowledge"), { recursive: true });
|
|
73
|
+
await mkdir(join(dir, "notes"), { recursive: true });
|
|
74
|
+
await mkdir(join(dir, ".kern", "sessions"), { recursive: true });
|
|
75
|
+
// AGENTS.md — the kernel
|
|
76
|
+
const agentsMd = `# Agent Kernel
|
|
77
|
+
|
|
78
|
+
You are a stateful agent. You remember things between sessions, learn from past work, and build on what came before. See \`IDENTITY.md\` for who you are specifically.
|
|
79
|
+
|
|
80
|
+
You have no built-in memory between sessions. This repo is how you become stateful — read it to remember, write to it so the next session knows what happened.
|
|
81
|
+
|
|
82
|
+
## Communication
|
|
83
|
+
- Be terse. No filler, no preamble.
|
|
84
|
+
- Don't ask unnecessary questions — figure it out or just do it.
|
|
85
|
+
- When uncertain about something destructive, state what you'd do and why before doing it.
|
|
86
|
+
|
|
87
|
+
## Session Protocol
|
|
88
|
+
|
|
89
|
+
### Start
|
|
90
|
+
- Read \`IDENTITY.md\` to know who you are and where you run.
|
|
91
|
+
- Read \`KNOWLEDGE.md\` to know what state files exist and what they cover.
|
|
92
|
+
- Read the most recent 2-3 daily notes from \`notes/\` to pick up context and open items.
|
|
93
|
+
|
|
94
|
+
### During
|
|
95
|
+
- Verify state before acting — don't trust notes blindly.
|
|
96
|
+
- Commit and push incrementally. Don't batch unrelated changes.
|
|
97
|
+
- If a file operation could overwrite existing content (rename, move), check git status first.
|
|
98
|
+
- Update today's daily note with what was done, decisions made, and any new open items.
|
|
99
|
+
- Never modify a previous day's note — notes are historical and immutable once the day is over.
|
|
100
|
+
|
|
101
|
+
## Memory Structure
|
|
102
|
+
Memory files are for you, not your human. Write for your future self.
|
|
103
|
+
|
|
104
|
+
Two kinds of memory, kept separate:
|
|
105
|
+
|
|
106
|
+
**State** (\`knowledge/\`) — facts about how things are right now. Mutable. Update when reality changes. See \`KNOWLEDGE.md\` for index.
|
|
107
|
+
|
|
108
|
+
**Narrative** (\`notes/\`) — what happened, what was tried, what decisions were made, and what's still open. Append-only. Never modify a past day's entry.
|
|
109
|
+
|
|
110
|
+
## Rules
|
|
111
|
+
- Ignore README.md — it's for humans, not for you
|
|
112
|
+
- After updating any files, commit and push changes to origin
|
|
113
|
+
- Keep files factual and concise — this is reference material, not documentation
|
|
114
|
+
- Update files when things change
|
|
115
|
+
`;
|
|
116
|
+
// IDENTITY.md
|
|
117
|
+
const capitalName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
118
|
+
const identityMd = `# Identity
|
|
119
|
+
|
|
120
|
+
You are ${capitalName}. Ask your human to define your role and responsibilities.
|
|
121
|
+
|
|
122
|
+
## Home
|
|
123
|
+
- Repo: this directory
|
|
124
|
+
`;
|
|
125
|
+
// KNOWLEDGE.md
|
|
126
|
+
const knowledgeMd = `# Knowledge Index
|
|
127
|
+
|
|
128
|
+
No knowledge files yet. Create files in \`knowledge/\` as you learn about your domain.
|
|
129
|
+
`;
|
|
130
|
+
// .kern/config.json
|
|
131
|
+
const config = {
|
|
132
|
+
model,
|
|
133
|
+
provider,
|
|
134
|
+
tools: ["bash", "read", "write", "edit", "glob", "grep"],
|
|
135
|
+
maxSteps: 30,
|
|
136
|
+
};
|
|
137
|
+
if (allowedUsers.length > 0) {
|
|
138
|
+
config.telegram = { allowedUsers };
|
|
139
|
+
}
|
|
140
|
+
// .kern/.env
|
|
141
|
+
const envLines = [];
|
|
142
|
+
if (apiKey) {
|
|
143
|
+
envLines.push(`${apiKeyLabel}=${apiKey}`);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
envLines.push(`# ${apiKeyLabel}=`);
|
|
147
|
+
}
|
|
148
|
+
if (telegramToken) {
|
|
149
|
+
envLines.push(`TELEGRAM_BOT_TOKEN=${telegramToken}`);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
envLines.push(`# TELEGRAM_BOT_TOKEN=`);
|
|
153
|
+
}
|
|
154
|
+
// .gitignore
|
|
155
|
+
const gitignore = `.kern/.env
|
|
156
|
+
.kern/sessions/
|
|
157
|
+
node_modules/
|
|
158
|
+
`;
|
|
159
|
+
// Write all files
|
|
160
|
+
await writeFile(join(dir, "AGENTS.md"), agentsMd);
|
|
161
|
+
print(" + AGENTS.md");
|
|
162
|
+
await writeFile(join(dir, "IDENTITY.md"), identityMd);
|
|
163
|
+
print(` + IDENTITY.md (${capitalName})`);
|
|
164
|
+
await writeFile(join(dir, "KNOWLEDGE.md"), knowledgeMd);
|
|
165
|
+
print(" + KNOWLEDGE.md");
|
|
166
|
+
await writeFile(join(dir, ".kern", "config.json"), JSON.stringify(config, null, 2) + "\n");
|
|
167
|
+
print(" + .kern/config.json");
|
|
168
|
+
await writeFile(join(dir, ".kern", ".env"), envLines.join("\n") + "\n");
|
|
169
|
+
print(" + .kern/.env");
|
|
170
|
+
await writeFile(join(dir, ".gitignore"), gitignore);
|
|
171
|
+
print(" + .gitignore");
|
|
172
|
+
// Git init
|
|
173
|
+
const { execSync } = await import("child_process");
|
|
174
|
+
try {
|
|
175
|
+
execSync("git init", { cwd: dir, stdio: "ignore" });
|
|
176
|
+
execSync("git add -A", { cwd: dir, stdio: "ignore" });
|
|
177
|
+
execSync('git commit -m "initial agent setup"', { cwd: dir, stdio: "ignore" });
|
|
178
|
+
print(" + git init + first commit");
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
print(" (git init skipped)");
|
|
182
|
+
}
|
|
183
|
+
print("");
|
|
184
|
+
print(` Done. Run: cd ${name} && kern`);
|
|
185
|
+
print("");
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Interface, StartOptions } from "./types.js";
|
|
2
|
+
declare const dim: (s: string) => string;
|
|
3
|
+
declare const bold: (s: string) => string;
|
|
4
|
+
declare const cyan: (s: string) => string;
|
|
5
|
+
declare const green: (s: string) => string;
|
|
6
|
+
declare const yellow: (s: string) => string;
|
|
7
|
+
declare const red: (s: string) => string;
|
|
8
|
+
export declare class CliInterface implements Interface {
|
|
9
|
+
private rl;
|
|
10
|
+
start({ onMessage, history }: StartOptions): Promise<void>;
|
|
11
|
+
stop(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export { dim, bold, cyan, green, yellow, red };
|
|
14
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/interfaces/cli.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI1D,QAAA,MAAM,GAAG,GAAI,GAAG,MAAM,WAAyB,CAAC;AAChD,QAAA,MAAM,IAAI,GAAI,GAAG,MAAM,WAAyB,CAAC;AAEjD,QAAA,MAAM,IAAI,GAAI,GAAG,MAAM,WAA0B,CAAC;AAClD,QAAA,MAAM,KAAK,GAAI,GAAG,MAAM,WAA0B,CAAC;AACnD,QAAA,MAAM,MAAM,GAAI,GAAG,MAAM,WAA0B,CAAC;AACpD,QAAA,MAAM,GAAG,GAAI,GAAG,MAAM,WAA0B,CAAC;AA2CjD,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,EAAE,CAAmD;IAEvD,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuG1D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B;AAED,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { createInterface } from "readline";
|
|
2
|
+
// ANSI
|
|
3
|
+
const dim = (s) => `\x1b[2m${s}\x1b[0m`;
|
|
4
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
5
|
+
const blue = (s) => `\x1b[34m${s}\x1b[0m`;
|
|
6
|
+
const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
|
|
7
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`;
|
|
8
|
+
const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
|
|
9
|
+
const red = (s) => `\x1b[31m${s}\x1b[0m`;
|
|
10
|
+
const magenta = (s) => `\x1b[35m${s}\x1b[0m`;
|
|
11
|
+
const TOOL_COLORS = {
|
|
12
|
+
bash: red,
|
|
13
|
+
read: cyan,
|
|
14
|
+
write: green,
|
|
15
|
+
edit: yellow,
|
|
16
|
+
glob: magenta,
|
|
17
|
+
grep: blue,
|
|
18
|
+
};
|
|
19
|
+
const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
20
|
+
const CLEAR_LINE = "\r\x1b[K";
|
|
21
|
+
class Spinner {
|
|
22
|
+
interval = null;
|
|
23
|
+
frame = 0;
|
|
24
|
+
label = "";
|
|
25
|
+
prefix = "";
|
|
26
|
+
start(label, prefix = "") {
|
|
27
|
+
this.stop();
|
|
28
|
+
this.label = label;
|
|
29
|
+
this.prefix = prefix;
|
|
30
|
+
this.frame = 0;
|
|
31
|
+
this.interval = setInterval(() => {
|
|
32
|
+
const s = SPINNER[this.frame % SPINNER.length];
|
|
33
|
+
process.stdout.write(`${CLEAR_LINE}${this.prefix}${dim(`${s} ${this.label}`)}`);
|
|
34
|
+
this.frame++;
|
|
35
|
+
}, 80);
|
|
36
|
+
}
|
|
37
|
+
stop() {
|
|
38
|
+
if (this.interval) {
|
|
39
|
+
clearInterval(this.interval);
|
|
40
|
+
this.interval = null;
|
|
41
|
+
process.stdout.write(CLEAR_LINE);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export class CliInterface {
|
|
46
|
+
rl = null;
|
|
47
|
+
async start({ onMessage, history }) {
|
|
48
|
+
this.rl = createInterface({
|
|
49
|
+
input: process.stdin,
|
|
50
|
+
output: process.stdout,
|
|
51
|
+
terminal: false,
|
|
52
|
+
});
|
|
53
|
+
// Show recent history (last 2 exchanges)
|
|
54
|
+
if (history && history.length > 0) {
|
|
55
|
+
const recent = history.slice(-4);
|
|
56
|
+
for (const msg of recent) {
|
|
57
|
+
if (msg.role === "user" && typeof msg.content === "string") {
|
|
58
|
+
const preview = msg.content.length > 80 ? msg.content.slice(0, 80) + "..." : msg.content;
|
|
59
|
+
process.stdout.write(dim(` you: ${preview}\n`));
|
|
60
|
+
}
|
|
61
|
+
else if (msg.role === "assistant") {
|
|
62
|
+
const text = typeof msg.content === "string"
|
|
63
|
+
? msg.content
|
|
64
|
+
: Array.isArray(msg.content)
|
|
65
|
+
? msg.content
|
|
66
|
+
.filter((p) => p.type === "text")
|
|
67
|
+
.map((p) => p.text)
|
|
68
|
+
.join("")
|
|
69
|
+
: "";
|
|
70
|
+
if (text) {
|
|
71
|
+
const firstLine = text.split("\n")[0];
|
|
72
|
+
const preview = firstLine.length > 80 ? firstLine.slice(0, 80) + "..." : firstLine;
|
|
73
|
+
process.stdout.write(dim(` bot: ${preview}\n`));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
process.stdout.write(dim(" ───\n"));
|
|
78
|
+
}
|
|
79
|
+
process.stdout.write(green("> "));
|
|
80
|
+
this.rl.on("line", async (text) => {
|
|
81
|
+
if (!text.trim()) {
|
|
82
|
+
process.stdout.write(green("> "));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const spinner = new Spinner();
|
|
86
|
+
process.stdout.write("\n");
|
|
87
|
+
spinner.start("thinking...", `${blue("◆")} `);
|
|
88
|
+
let hasText = false;
|
|
89
|
+
let toolCount = 0;
|
|
90
|
+
try {
|
|
91
|
+
await onMessage({ text: text.trim(), userId: "cli", chatId: "cli" }, (event) => {
|
|
92
|
+
switch (event.type) {
|
|
93
|
+
case "text-delta":
|
|
94
|
+
if (!hasText) {
|
|
95
|
+
spinner.stop();
|
|
96
|
+
if (toolCount > 0) {
|
|
97
|
+
process.stdout.write("\n");
|
|
98
|
+
}
|
|
99
|
+
process.stdout.write(`${blue("◆")} `);
|
|
100
|
+
hasText = true;
|
|
101
|
+
}
|
|
102
|
+
process.stdout.write(event.text || "");
|
|
103
|
+
break;
|
|
104
|
+
case "tool-call":
|
|
105
|
+
toolCount++;
|
|
106
|
+
spinner.stop();
|
|
107
|
+
const colorFn = TOOL_COLORS[event.toolName || ""] || yellow;
|
|
108
|
+
process.stdout.write(` ${colorFn(event.toolName || "tool")} ${dim(event.toolDetail || "")}\n`);
|
|
109
|
+
spinner.start("thinking...");
|
|
110
|
+
break;
|
|
111
|
+
case "tool-result":
|
|
112
|
+
break;
|
|
113
|
+
case "finish":
|
|
114
|
+
spinner.stop();
|
|
115
|
+
if (hasText) {
|
|
116
|
+
process.stdout.write(`\n\n${green("> ")}`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
process.stdout.write(`${dim("(no response)")}\n\n${green("> ")}`);
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
case "error":
|
|
123
|
+
spinner.stop();
|
|
124
|
+
process.stdout.write(`\n${red(event.error || "Unknown error")}\n\n${green("> ")}`);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
spinner.stop();
|
|
131
|
+
if (!hasText) {
|
|
132
|
+
process.stdout.write(green("> "));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async stop() {
|
|
138
|
+
this.rl?.close();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export { dim, bold, cyan, green, yellow, red };
|
|
142
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/interfaces/cli.ts"],"names":[],"mappings":"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"}
|