kern-ai 0.25.0 → 0.26.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 +77 -158
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +2 -1
- package/dist/model.js.map +1 -1
- package/dist/plugins/exec/jobs.d.ts +38 -0
- package/dist/plugins/exec/jobs.d.ts.map +1 -0
- package/dist/plugins/exec/jobs.js +133 -0
- package/dist/plugins/exec/jobs.js.map +1 -0
- package/dist/plugins/exec/plugin.d.ts +3 -0
- package/dist/plugins/exec/plugin.d.ts.map +1 -0
- package/dist/plugins/exec/plugin.js +221 -0
- package/dist/plugins/exec/plugin.js.map +1 -0
- package/dist/plugins/recall/plugin.d.ts.map +1 -1
- package/dist/plugins/recall/plugin.js +2 -1
- package/dist/plugins/recall/plugin.js.map +1 -1
- package/dist/plugins/recall/tool.d.ts +1 -0
- package/dist/plugins/recall/tool.d.ts.map +1 -1
- package/dist/plugins/recall/tool.js +10 -0
- package/dist/plugins/recall/tool.js.map +1 -1
- package/dist/tools/webfetch.d.ts.map +1 -1
- package/dist/tools/webfetch.js +91 -32
- package/dist/tools/webfetch.js.map +1 -1
- package/dist/tools/websearch.d.ts.map +1 -1
- package/dist/tools/websearch.js +62 -25
- package/dist/tools/websearch.js.map +1 -1
- package/docs/config.md +6 -0
- package/docs/dashboards.md +152 -0
- package/docs/tools.md +6 -4
- package/package.json +1 -1
- package/web/out/404.html +1 -1
- package/web/out/__next.__PAGE__.txt +2 -2
- package/web/out/__next._full.txt +3 -3
- package/web/out/__next._head.txt +1 -1
- package/web/out/__next._index.txt +2 -2
- package/web/out/__next._tree.txt +2 -2
- package/web/out/_next/static/chunks/0oc6l~f8ptro~.css +1 -0
- package/web/out/_next/static/chunks/182ryh_d5jtxt.js +79 -0
- package/web/out/_not-found/__next._full.txt +2 -2
- package/web/out/_not-found/__next._head.txt +1 -1
- package/web/out/_not-found/__next._index.txt +2 -2
- package/web/out/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/web/out/_not-found/__next._not-found.txt +1 -1
- package/web/out/_not-found/__next._tree.txt +2 -2
- package/web/out/_not-found.html +1 -1
- package/web/out/_not-found.txt +2 -2
- package/web/out/index.html +1 -1
- package/web/out/index.txt +3 -3
- package/web/out/_next/static/chunks/0j5nr7atp7bug.js +0 -79
- package/web/out/_next/static/chunks/0n82agh_mw.g~.css +0 -1
- /package/web/out/_next/static/{vvW4fPfaiVMC-l-E9E96V → 3zMW7eccqQlKYeGSJcFb_}/_buildManifest.js +0 -0
- /package/web/out/_next/static/{vvW4fPfaiVMC-l-E9E96V → 3zMW7eccqQlKYeGSJcFb_}/_clientMiddlewareManifest.js +0 -0
- /package/web/out/_next/static/{vvW4fPfaiVMC-l-E9E96V → 3zMW7eccqQlKYeGSJcFb_}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# kern
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Agents that do the work and show it.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Agents that run on your machine, use real tools, remember everything, and publish their own dashboards. Not chatbots — autonomous workers with one brain across every channel.
|
|
6
6
|
|
|
7
|
-

|
|
8
8
|
|
|
9
9
|
## Why kern
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **A folder is the agent** — AGENTS.md defines behavior, IDENTITY.md defines who it is, knowledge/ and notes/ are its memory. Everything is plain text, git-tracked, and inspectable.
|
|
16
|
-
- **No external infra** — no hosted server or managed database required. Runs locally with a folder, SQLite, an API key, and `npm install -g kern-ai`.
|
|
11
|
+
- **One brain, every channel** — terminal, browser, Telegram, Slack feed into one session. The agent knows who's talking, what channel it's in, and what happened 10,000 messages ago.
|
|
12
|
+
- **Memory that compounds** — conversations segmented by topic, summarized into a hierarchy, compressed into context. Semantic recall over everything. The agent gets better the longer it runs.
|
|
13
|
+
- **Agents build their own UI** — dashboards with live data, served from the agent, displayed in a side panel. Not chat — real interfaces that update themselves.
|
|
14
|
+
- **Your infra, your data** — runs on your laptop, server, or homelab. The whole agent is a git-tracked folder. Pay only for API tokens — or use Ollama for fully local, zero-cost inference.
|
|
17
15
|
|
|
18
16
|
kern pairs with [agent-kernel](https://github.com/oguzbilgic/agent-kernel) — the kernel defines how an agent remembers, kern runs it.
|
|
19
17
|
|
|
@@ -29,38 +27,46 @@ The init wizard scaffolds your agent, asks for a provider and API key, then star
|
|
|
29
27
|
|
|
30
28
|
For automation: `kern init my-agent --api-key sk-or-...` (no prompts, defaults to openrouter + opus 4.6). For Ollama: `kern init my-agent --provider ollama --api-key http://localhost:11434 --model gemma4:31b`.
|
|
31
29
|
|
|
32
|
-
##
|
|
30
|
+
## Dashboards
|
|
31
|
+
|
|
32
|
+

|
|
33
|
+
|
|
34
|
+
Agents create and maintain their own dashboards — HTML pages with live data, served from the agent and displayed in the web UI side panel. Not chat transcripts. Real interfaces that update themselves.
|
|
33
35
|
|
|
34
36
|
```
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
#engineering ─────┤
|
|
39
|
-
Slack DM ─────────┘
|
|
37
|
+
dashboards/homelab/
|
|
38
|
+
index.html # visualization
|
|
39
|
+
data.json # structured data (injected as window.__KERN_DATA__)
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
The agent writes `data.json`, creates the HTML, then calls `render({ dashboard: "homelab" })` to display it. Dashboards appear in the sidebar and can be switched from the panel header.
|
|
43
|
+
|
|
44
|
+
[Dashboards docs](docs/dashboards.md) · [Blog: Why every agent needs a dashboard](https://kern-ai.com/blog/agent-dashboards)
|
|
45
|
+
|
|
46
|
+
## Memory
|
|
47
|
+
|
|
48
|
+

|
|
49
|
+
|
|
50
|
+
Conversations are automatically segmented by topic, summarized, and rolled up into a hierarchy (L0 → L1 → L2). When old messages are trimmed from context, compressed summaries take their place — the agent sees its full history at decreasing resolution. Semantic recall searches everything.
|
|
51
|
+
|
|
52
|
+
The web UI includes a Memory overlay with five tabs for inspecting sessions, segments, notes, recall, and the full context pipeline with token breakdowns.
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
[Memory docs](docs/memory.md) · [Blog: Lossless context management](https://kern-ai.com/blog/lossless-context-management) · [Blog: See inside your agent's brain](https://kern-ai.com/blog/memory-ui)
|
|
45
55
|
|
|
46
|
-
|
|
56
|
+
## One session
|
|
47
57
|
|
|
48
58
|
```
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
USERS.md # paired users with roles and guardrails
|
|
54
|
-
knowledge/ # mutable state files
|
|
55
|
-
notes/ # daily logs (append-only)
|
|
56
|
-
.kern/
|
|
57
|
-
config.json # model, provider, toolScope (committed)
|
|
58
|
-
.env # API keys, bot tokens (gitignored)
|
|
59
|
-
sessions/ # conversation history (gitignored)
|
|
60
|
-
recall.db # memory database (gitignored)
|
|
59
|
+
Terminal ─────┐
|
|
60
|
+
Web UI ───────┤
|
|
61
|
+
Telegram ─────┤── one session
|
|
62
|
+
Slack ────────┘
|
|
61
63
|
```
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
Every interface feeds into the same session. Message from Telegram, pick up in the terminal, continue in the browser. Each message carries metadata — who said it, which channel, when — so the agent connects context across all of them without losing track.
|
|
66
|
+
|
|
67
|
+
The agent reads and writes its own memory files through tools — takes notes, updates knowledge, commits to git. The next time you talk to it, from any interface, it picks up exactly where it left off.
|
|
68
|
+
|
|
69
|
+
[Blog: Why your agent needs one session](https://kern-ai.com/blog/why-your-agent-needs-one-session)
|
|
64
70
|
|
|
65
71
|
## CLI
|
|
66
72
|
|
|
@@ -69,128 +75,44 @@ kern init <name> # create or configure an agent
|
|
|
69
75
|
kern start [name|path] # start agents in background
|
|
70
76
|
kern stop [name] # stop agents
|
|
71
77
|
kern restart [name] # restart agents
|
|
72
|
-
kern install [name|--web|--proxy] # install systemd services
|
|
73
|
-
kern uninstall [name] # remove systemd services
|
|
78
|
+
kern install [name|--web|--proxy] # install systemd services
|
|
74
79
|
kern tui [name] # interactive chat
|
|
75
|
-
kern web <start|stop
|
|
76
|
-
kern proxy <start|stop|
|
|
80
|
+
kern web <start|stop> # static web UI server
|
|
81
|
+
kern proxy <start|stop|token> # authenticated reverse proxy
|
|
77
82
|
kern logs [name] # follow agent logs
|
|
78
|
-
kern list # show all agents
|
|
79
|
-
kern remove <name> # unregister an agent
|
|
83
|
+
kern list # show all agents and services
|
|
80
84
|
kern backup <name> # backup agent to .tar.gz
|
|
81
|
-
kern restore <file> # restore agent from backup
|
|
82
|
-
kern import opencode # import session from OpenCode
|
|
83
85
|
```
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
### Web UI
|
|
88
|
-
|
|
89
|
-
`kern web start` serves the web UI as static files (default port 8080). Connect to agents directly from the sidebar by entering their URL and token.
|
|
90
|
-
|
|
91
|
-
`kern proxy start` launches an optional authenticated reverse proxy (default port 9000) that discovers local agents and proxies requests to them.
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
kern web start # start static web server
|
|
95
|
-
kern proxy start # start proxy, prints URL with token
|
|
96
|
-
kern proxy token # print URL with token again
|
|
97
|
-
```
|
|
87
|
+
### Connecting
|
|
98
88
|
|
|
99
|
-
The web UI
|
|
100
|
-
- **Direct** — enter the agent's URL and `KERN_AUTH_TOKEN` in the sidebar. No proxy needed.
|
|
101
|
-
- **Via proxy** — connect to a `kern proxy` server with `KERN_PROXY_TOKEN`. The proxy discovers and forwards to local agents.
|
|
89
|
+
Agents bind to `0.0.0.0` on sticky ports (4100-4999), accessible over Tailscale or LAN. The web UI connects directly — enter the agent's URL and `KERN_AUTH_TOKEN` in the sidebar.
|
|
102
90
|
|
|
103
|
-
|
|
91
|
+
Optionally, `kern proxy start` launches an authenticated reverse proxy that discovers and forwards to local agents.
|
|
104
92
|
|
|
105
93
|
### Slash commands
|
|
106
94
|
|
|
107
|
-
Type these in any channel (TUI, Web, Telegram, Slack). Handled by the runtime — no LLM call, instant response.
|
|
108
|
-
|
|
109
95
|
```
|
|
110
96
|
/status # agent status, model, uptime, session size
|
|
111
97
|
/restart # restart the agent daemon
|
|
112
98
|
/help # list available commands
|
|
113
99
|
```
|
|
114
100
|
|
|
115
|
-
##
|
|
116
|
-
|
|
117
|
-
The first person to message the bot becomes the operator — auto-paired, no code needed. Every user after pairs with a code:
|
|
118
|
-
|
|
119
|
-
1. Unknown user messages the bot → gets a `KERN-XXXX` code
|
|
120
|
-
2. User shares code with the operator
|
|
121
|
-
3. Operator approves: tell the agent, or `kern pair atlas KERN-XXXX` from CLI
|
|
122
|
-
4. Agent pairs them and writes USERS.md with identity and access notes
|
|
123
|
-
|
|
124
|
-
No allowlists. The agent manages its own access.
|
|
125
|
-
|
|
126
|
-
## Telegram
|
|
127
|
-
|
|
128
|
-
Set `TELEGRAM_BOT_TOKEN` in `.kern/.env` and kern connects via long polling. No public URL needed — works behind NAT. Messages show up in real time in the TUI.
|
|
129
|
-
|
|
130
|
-
## Slack
|
|
131
|
-
|
|
132
|
-
Set `SLACK_BOT_TOKEN` and `SLACK_APP_TOKEN` in `.kern/.env`. Uses Socket Mode — no public URL needed.
|
|
133
|
-
|
|
134
|
-
- **DMs**: pairing required, same as Telegram
|
|
135
|
-
- **Channels**: agent reads all messages, only responds when @mentioned or relevant
|
|
136
|
-
- **NO_REPLY**: agent silently absorbs channel context without cluttering the conversation
|
|
137
|
-
|
|
138
|
-
Invite the bot to channels where it should listen.
|
|
139
|
-
|
|
140
|
-
## Media
|
|
141
|
-
|
|
142
|
-
Send images and files through any interface — Telegram, Slack, or Web UI. Files are stored locally in `.kern/media/` with content-addressed naming.
|
|
143
|
-
|
|
144
|
-
By default, images are pre-digested: a vision model describes each image once, and the description is cached. The chat model sees text instead of raw image data — works with any model, saves tokens. Set `mediaDigest: false` to send raw images inline instead.
|
|
145
|
-
|
|
146
|
-
See [Media docs](docs/media.md) for details.
|
|
147
|
-
|
|
148
|
-
## Memory
|
|
149
|
-
|
|
150
|
-
Agents remember across sessions through three mechanisms:
|
|
151
|
-
|
|
152
|
-
- **Files** — `knowledge/` for mutable state, `notes/` for daily logs. The agent reads and writes these through tools. Git-tracked, inspectable, portable.
|
|
153
|
-
- **Recall** — semantic search over all past conversations. Messages are embedded and stored in a local SQLite database (`recall.db`). The agent uses the `recall` tool to search by query with optional date filters, or load raw messages from a specific session.
|
|
154
|
-
- **Segments** — messages are automatically grouped into topic-coherent segments, summarized, and rolled up into a hierarchy (L0 → L1 → L2). When old messages are trimmed from context, compressed summaries are injected in their place — the agent sees its full conversation history at decreasing resolution.
|
|
155
|
-
|
|
156
|
-
On startup, the agent's system prompt is automatically injected with:
|
|
157
|
-
- The latest daily note (full content)
|
|
158
|
-
- An LLM-generated summary of the previous 5 daily notes
|
|
159
|
-
- Compressed conversation history from segments (when messages have been trimmed)
|
|
160
|
-
|
|
161
|
-
This means the agent boots with recent context — no manual reading required. Summaries are cached in SQLite and regenerated in the background on day rollover.
|
|
162
|
-
|
|
163
|
-
### Memory UI
|
|
164
|
-
|
|
165
|
-
The web UI includes a Memory overlay with five tabs for examining all aspects of agent memory: sessions, segments, notes, recall, and context. See the full context pipeline — from raw messages through segment hierarchy to the final system prompt — with token breakdowns and compression ratios.
|
|
166
|
-
|
|
167
|
-

|
|
168
|
-
|
|
169
|
-
## Heartbeat
|
|
170
|
-
|
|
171
|
-
Kern sends a periodic `[heartbeat]` to the agent. The agent reviews notes, updates knowledge files, and messages the operator if something needs attention. Visible in the TUI only — Telegram and Slack never see it.
|
|
172
|
-
|
|
173
|
-
```json
|
|
174
|
-
{
|
|
175
|
-
"heartbeatInterval": 60
|
|
176
|
-
}
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
Interval in minutes. Default 60 (1 hour). Set to 0 to disable.
|
|
101
|
+
## Interfaces
|
|
180
102
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
kern
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
103
|
+
| Interface | Setup |
|
|
104
|
+
|-----------|-------|
|
|
105
|
+
| **Terminal** | `kern tui` — interactive chat |
|
|
106
|
+
| **Web UI** | `kern web start` — browser at port 8080 |
|
|
107
|
+
| **Telegram** | Set `TELEGRAM_BOT_TOKEN` in `.kern/.env` |
|
|
108
|
+
| **Slack** | Set `SLACK_BOT_TOKEN` and `SLACK_APP_TOKEN` in `.kern/.env` |
|
|
109
|
+
| **Desktop** | macOS app via Tauri ([releases](https://github.com/oguzbilgic/kern-ai/releases)) |
|
|
188
110
|
|
|
189
|
-
|
|
111
|
+
First Telegram/Slack user is auto-paired as operator. Others pair with `KERN-XXXX` codes.
|
|
190
112
|
|
|
191
113
|
## Configuration
|
|
192
114
|
|
|
193
|
-
###
|
|
115
|
+
### `.kern/config.json`
|
|
194
116
|
|
|
195
117
|
```json
|
|
196
118
|
{
|
|
@@ -198,44 +120,41 @@ Structured, leveled logs with colored labels. Stored in `.kern/logs/kern.log`. A
|
|
|
198
120
|
"provider": "openrouter",
|
|
199
121
|
"toolScope": "full",
|
|
200
122
|
"maxContextTokens": 100000,
|
|
201
|
-
"maxToolResultChars": 20000,
|
|
202
123
|
"summaryBudget": 0.75
|
|
203
124
|
}
|
|
204
125
|
```
|
|
205
126
|
|
|
206
|
-
`maxContextTokens` controls the sliding context window — older messages are trimmed to stay within budget. `maxToolResultChars` caps individual tool results in context (full results stay in session JSONL and are searchable via recall). `summaryBudget` controls what fraction of the context window is reserved for compressed segment summaries when old messages are trimmed (default 75%, cached via prompt caching so effectively free). Set to `0` to disable.
|
|
207
|
-
|
|
208
|
-
Agent auth tokens are auto-generated on first start and stored in `.kern/.env`. The proxy injects them automatically — no manual setup needed.
|
|
209
|
-
|
|
210
|
-
### Global: `~/.kern/config.json`
|
|
211
|
-
|
|
212
|
-
```json
|
|
213
|
-
{
|
|
214
|
-
"web_port": 8080,
|
|
215
|
-
"proxy_port": 9000
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
Controls the `kern web` and `kern proxy` servers. Optional — defaults apply if the file doesn't exist.
|
|
220
|
-
|
|
221
127
|
### Tool scopes
|
|
222
128
|
|
|
223
|
-
- **full** — shell
|
|
224
|
-
- **write** —
|
|
225
|
-
- **read** — read
|
|
226
|
-
|
|
227
|
-
Shell tool is platform-specific: `bash` on Unix/Linux, `pwsh` on Windows. Selected automatically.
|
|
129
|
+
- **full** — shell, read, write, edit, glob, grep, webfetch, websearch, kern, message, recall, pdf, image, render
|
|
130
|
+
- **write** — everything except shell
|
|
131
|
+
- **read** — read-only tools
|
|
228
132
|
|
|
229
133
|
### Providers
|
|
230
134
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
135
|
+
| Provider | Description |
|
|
136
|
+
|----------|-------------|
|
|
137
|
+
| **openrouter** | Any model via OpenRouter (default) |
|
|
138
|
+
| **anthropic** | Direct Anthropic API |
|
|
139
|
+
| **openai** | OpenAI / Azure |
|
|
140
|
+
| **ollama** | Local models via [Ollama](https://ollama.com) |
|
|
141
|
+
|
|
142
|
+
Models can be mixed per role: `model` for chat, `embeddingModel` for recall, `summaryModel` for segments, `mediaModel` for vision.
|
|
235
143
|
|
|
236
144
|
## Documentation
|
|
237
145
|
|
|
238
|
-
|
|
146
|
+
- [Get started](docs/get-started.md)
|
|
147
|
+
- [Configuration](docs/config.md)
|
|
148
|
+
- [Architecture](docs/architecture.md)
|
|
149
|
+
- [Memory](docs/memory.md)
|
|
150
|
+
- [Dashboards](docs/dashboards.md)
|
|
151
|
+
- [Context & segments](docs/context.md)
|
|
152
|
+
- [Prompt caching](docs/caching.md)
|
|
153
|
+
- [Media](docs/media.md)
|
|
154
|
+
- [Tools](docs/tools.md)
|
|
155
|
+
- [Interfaces](docs/interfaces.md)
|
|
156
|
+
- [CLI commands](docs/commands.md)
|
|
157
|
+
- [Pairing](docs/pairing.md)
|
|
239
158
|
|
|
240
159
|
## Built with
|
|
241
160
|
|
package/dist/model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAqC9C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,IAAI,CAuBlG;AAED;;;GAGG;AAEH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAYxD;AAED;;;GAGG;AAEH,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,GAAG,CAwCnD"}
|
package/dist/model.js
CHANGED
|
@@ -3,7 +3,8 @@ import { createOpenAI } from "@ai-sdk/openai";
|
|
|
3
3
|
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
|
|
4
4
|
const OPENROUTER_HEADERS = {
|
|
5
5
|
"HTTP-Referer": "https://github.com/oguzbilgic/kern-ai",
|
|
6
|
-
"X-Title": "
|
|
6
|
+
"X-Title": "Kern Agent",
|
|
7
|
+
"X-OpenRouter-Title": "Kern Agent",
|
|
7
8
|
"X-OpenRouter-Categories": "cli-agent,personal-agent",
|
|
8
9
|
};
|
|
9
10
|
/**
|
package/dist/model.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAI/D,MAAM,kBAAkB,GAAG;IACzB,cAAc,EAAE,uCAAuC;IACvD,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface Job {
|
|
2
|
+
id: string;
|
|
3
|
+
pid: number;
|
|
4
|
+
command: string;
|
|
5
|
+
status: "running" | "done" | "failed";
|
|
6
|
+
logFile: string;
|
|
7
|
+
startedAt: number;
|
|
8
|
+
exitCode: number | null;
|
|
9
|
+
}
|
|
10
|
+
/** Return the jobs directory for a given agent dir, creating it if needed. */
|
|
11
|
+
export declare function jobsDir(agentDir: string): string;
|
|
12
|
+
/** Register a new background job. */
|
|
13
|
+
export declare function addJob(job: Job): void;
|
|
14
|
+
/** Get a job by ID. */
|
|
15
|
+
export declare function getJob(id: string): Job | undefined;
|
|
16
|
+
/** List all tracked jobs. */
|
|
17
|
+
export declare function listJobs(): Job[];
|
|
18
|
+
/** Mark a job as complete. */
|
|
19
|
+
export declare function completeJob(id: string, exitCode: number | null): void;
|
|
20
|
+
/** Set exit code on a job without changing status (used by child close handler). */
|
|
21
|
+
export declare function setExitCode(id: string, code: number | null): void;
|
|
22
|
+
/** Remove a job from registry. */
|
|
23
|
+
export declare function removeJob(id: string): void;
|
|
24
|
+
/** Read the full contents of a log file. */
|
|
25
|
+
export declare function readLogFull(logFile: string): string;
|
|
26
|
+
/** Read the tail of a job's log file. */
|
|
27
|
+
export declare function readLogTail(logFile: string, lines?: number): string;
|
|
28
|
+
/** Clean up a job's log file (best-effort). */
|
|
29
|
+
export declare function cleanupLogFile(logFile: string): void;
|
|
30
|
+
type CompletionHandler = (job: Job, logTail: string) => void;
|
|
31
|
+
/** Start the PID reaper. Calls `onComplete` when a background job finishes. */
|
|
32
|
+
export declare function startReaper(onComplete: CompletionHandler, intervalMs?: number): void;
|
|
33
|
+
/** Stop the reaper. */
|
|
34
|
+
export declare function stopReaper(): void;
|
|
35
|
+
/** Kill all running background jobs (cleanup on shutdown). */
|
|
36
|
+
export declare function killAllJobs(): void;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=jobs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../../src/plugins/exec/jobs.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAID,8EAA8E;AAC9E,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED,qCAAqC;AACrC,wBAAgB,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAErC;AAED,uBAAuB;AACvB,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAElD;AAED,6BAA6B;AAC7B,wBAAgB,QAAQ,IAAI,GAAG,EAAE,CAEhC;AAED,8BAA8B;AAC9B,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAKrE;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGjE;AAED,kCAAkC;AAClC,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE1C;AAED,4CAA4C;AAC5C,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAc/D;AAED,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMpD;AAMD,KAAK,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAc7D,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,UAAU,EAAE,iBAAiB,EAAE,UAAU,SAAO,GAAG,IAAI,CAkBlF;AAED,uBAAuB;AACvB,wBAAgB,UAAU,IAAI,IAAI,CAKjC;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,IAAI,IAAI,CAUlC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { join } from "path";
|
|
2
|
+
import { mkdirSync, existsSync, unlinkSync, readFileSync } from "fs";
|
|
3
|
+
import { log } from "../../log.js";
|
|
4
|
+
const jobs = new Map();
|
|
5
|
+
/** Return the jobs directory for a given agent dir, creating it if needed. */
|
|
6
|
+
export function jobsDir(agentDir) {
|
|
7
|
+
const dir = join(agentDir, ".kern", "jobs");
|
|
8
|
+
if (!existsSync(dir))
|
|
9
|
+
mkdirSync(dir, { recursive: true });
|
|
10
|
+
return dir;
|
|
11
|
+
}
|
|
12
|
+
/** Register a new background job. */
|
|
13
|
+
export function addJob(job) {
|
|
14
|
+
jobs.set(job.id, job);
|
|
15
|
+
}
|
|
16
|
+
/** Get a job by ID. */
|
|
17
|
+
export function getJob(id) {
|
|
18
|
+
return jobs.get(id);
|
|
19
|
+
}
|
|
20
|
+
/** List all tracked jobs. */
|
|
21
|
+
export function listJobs() {
|
|
22
|
+
return Array.from(jobs.values());
|
|
23
|
+
}
|
|
24
|
+
/** Mark a job as complete. */
|
|
25
|
+
export function completeJob(id, exitCode) {
|
|
26
|
+
const job = jobs.get(id);
|
|
27
|
+
if (!job)
|
|
28
|
+
return;
|
|
29
|
+
job.status = exitCode === 0 ? "done" : "failed";
|
|
30
|
+
job.exitCode = exitCode;
|
|
31
|
+
}
|
|
32
|
+
/** Set exit code on a job without changing status (used by child close handler). */
|
|
33
|
+
export function setExitCode(id, code) {
|
|
34
|
+
const job = jobs.get(id);
|
|
35
|
+
if (job)
|
|
36
|
+
job.exitCode = code;
|
|
37
|
+
}
|
|
38
|
+
/** Remove a job from registry. */
|
|
39
|
+
export function removeJob(id) {
|
|
40
|
+
jobs.delete(id);
|
|
41
|
+
}
|
|
42
|
+
/** Read the full contents of a log file. */
|
|
43
|
+
export function readLogFull(logFile) {
|
|
44
|
+
try {
|
|
45
|
+
if (!existsSync(logFile))
|
|
46
|
+
return "(log file not found)";
|
|
47
|
+
return readFileSync(logFile, "utf-8");
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return "(failed to read log)";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Read the tail of a job's log file. */
|
|
54
|
+
export function readLogTail(logFile, lines = 20) {
|
|
55
|
+
try {
|
|
56
|
+
if (!existsSync(logFile))
|
|
57
|
+
return "(log file not found)";
|
|
58
|
+
const content = readFileSync(logFile, "utf-8");
|
|
59
|
+
const allLines = content.split("\n");
|
|
60
|
+
// Remove trailing empty string from final newline
|
|
61
|
+
if (allLines.length > 0 && allLines[allLines.length - 1] === "") {
|
|
62
|
+
allLines.pop();
|
|
63
|
+
}
|
|
64
|
+
const tail = allLines.slice(-lines).join("\n");
|
|
65
|
+
return tail;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return "(failed to read log)";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Clean up a job's log file (best-effort). */
|
|
72
|
+
export function cleanupLogFile(logFile) {
|
|
73
|
+
try {
|
|
74
|
+
if (existsSync(logFile))
|
|
75
|
+
unlinkSync(logFile);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// non-critical
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
let reaperInterval = null;
|
|
82
|
+
/** Check if a PID is still running via kill(pid, 0). */
|
|
83
|
+
function isRunning(pid) {
|
|
84
|
+
try {
|
|
85
|
+
process.kill(pid, 0);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Start the PID reaper. Calls `onComplete` when a background job finishes. */
|
|
93
|
+
export function startReaper(onComplete, intervalMs = 3000) {
|
|
94
|
+
if (reaperInterval)
|
|
95
|
+
return; // already running
|
|
96
|
+
reaperInterval = setInterval(() => {
|
|
97
|
+
for (const job of jobs.values()) {
|
|
98
|
+
if (job.status !== "running")
|
|
99
|
+
continue;
|
|
100
|
+
if (isRunning(job.pid))
|
|
101
|
+
continue;
|
|
102
|
+
// Process exited — transition status and fire callback.
|
|
103
|
+
// exitCode may already be set by the child "close" handler (via setExitCode),
|
|
104
|
+
// or null if the process was fully detached.
|
|
105
|
+
completeJob(job.id, job.exitCode);
|
|
106
|
+
const tail = readLogTail(job.logFile);
|
|
107
|
+
log("exec", `job ${job.id} finished (exit ${job.exitCode ?? "?"}): ${job.command.slice(0, 80)}`);
|
|
108
|
+
onComplete(job, tail);
|
|
109
|
+
}
|
|
110
|
+
}, intervalMs);
|
|
111
|
+
}
|
|
112
|
+
/** Stop the reaper. */
|
|
113
|
+
export function stopReaper() {
|
|
114
|
+
if (reaperInterval) {
|
|
115
|
+
clearInterval(reaperInterval);
|
|
116
|
+
reaperInterval = null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Kill all running background jobs (cleanup on shutdown). */
|
|
120
|
+
export function killAllJobs() {
|
|
121
|
+
for (const job of jobs.values()) {
|
|
122
|
+
if (job.status !== "running")
|
|
123
|
+
continue;
|
|
124
|
+
try {
|
|
125
|
+
process.kill(job.pid, "SIGTERM");
|
|
126
|
+
log("exec", `killed orphaned job ${job.id} (pid ${job.pid})`);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// already dead
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../../src/plugins/exec/jobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/exec/plugin.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,aAAa,CAAC;AAmN7D,eAAO,MAAM,UAAU,EAAE,UAuDxB,CAAC"}
|