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.
Files changed (52) hide show
  1. package/README.md +77 -158
  2. package/dist/model.d.ts.map +1 -1
  3. package/dist/model.js +2 -1
  4. package/dist/model.js.map +1 -1
  5. package/dist/plugins/exec/jobs.d.ts +38 -0
  6. package/dist/plugins/exec/jobs.d.ts.map +1 -0
  7. package/dist/plugins/exec/jobs.js +133 -0
  8. package/dist/plugins/exec/jobs.js.map +1 -0
  9. package/dist/plugins/exec/plugin.d.ts +3 -0
  10. package/dist/plugins/exec/plugin.d.ts.map +1 -0
  11. package/dist/plugins/exec/plugin.js +221 -0
  12. package/dist/plugins/exec/plugin.js.map +1 -0
  13. package/dist/plugins/recall/plugin.d.ts.map +1 -1
  14. package/dist/plugins/recall/plugin.js +2 -1
  15. package/dist/plugins/recall/plugin.js.map +1 -1
  16. package/dist/plugins/recall/tool.d.ts +1 -0
  17. package/dist/plugins/recall/tool.d.ts.map +1 -1
  18. package/dist/plugins/recall/tool.js +10 -0
  19. package/dist/plugins/recall/tool.js.map +1 -1
  20. package/dist/tools/webfetch.d.ts.map +1 -1
  21. package/dist/tools/webfetch.js +91 -32
  22. package/dist/tools/webfetch.js.map +1 -1
  23. package/dist/tools/websearch.d.ts.map +1 -1
  24. package/dist/tools/websearch.js +62 -25
  25. package/dist/tools/websearch.js.map +1 -1
  26. package/docs/config.md +6 -0
  27. package/docs/dashboards.md +152 -0
  28. package/docs/tools.md +6 -4
  29. package/package.json +1 -1
  30. package/web/out/404.html +1 -1
  31. package/web/out/__next.__PAGE__.txt +2 -2
  32. package/web/out/__next._full.txt +3 -3
  33. package/web/out/__next._head.txt +1 -1
  34. package/web/out/__next._index.txt +2 -2
  35. package/web/out/__next._tree.txt +2 -2
  36. package/web/out/_next/static/chunks/0oc6l~f8ptro~.css +1 -0
  37. package/web/out/_next/static/chunks/182ryh_d5jtxt.js +79 -0
  38. package/web/out/_not-found/__next._full.txt +2 -2
  39. package/web/out/_not-found/__next._head.txt +1 -1
  40. package/web/out/_not-found/__next._index.txt +2 -2
  41. package/web/out/_not-found/__next._not-found.__PAGE__.txt +1 -1
  42. package/web/out/_not-found/__next._not-found.txt +1 -1
  43. package/web/out/_not-found/__next._tree.txt +2 -2
  44. package/web/out/_not-found.html +1 -1
  45. package/web/out/_not-found.txt +2 -2
  46. package/web/out/index.html +1 -1
  47. package/web/out/index.txt +3 -3
  48. package/web/out/_next/static/chunks/0j5nr7atp7bug.js +0 -79
  49. package/web/out/_next/static/chunks/0n82agh_mw.g~.css +0 -1
  50. /package/web/out/_next/static/{vvW4fPfaiVMC-l-E9E96V → 3zMW7eccqQlKYeGSJcFb_}/_buildManifest.js +0 -0
  51. /package/web/out/_next/static/{vvW4fPfaiVMC-l-E9E96V → 3zMW7eccqQlKYeGSJcFb_}/_clientMiddlewareManifest.js +0 -0
  52. /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
- AI agents built for coworking.
3
+ Agents that do the work and show it.
4
4
 
5
- One brain across every channel. Your agent sits in Slack channels, Telegram DMs, the terminal, and the browser. It knows who's talking, reads the room, and remembers everything. Humans and agents, same channels, same conversation.
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
- ![kern web UI](https://kern-ai.com/images/web-ui.png)
7
+ ![kern web UI](https://kern-ai.com/images/agent-intranet.png)
8
8
 
9
9
  ## Why kern
10
10
 
11
- Most agent frameworks give you sessions that reset, memory that's a black box, or infrastructure you have to manage. kern takes a different approach:
12
-
13
- - **One brain** a single continuous session across every interface. Message from Telegram, pick up in the terminal, continue in the browser. The agent always knows what happened.
14
- - **Context-aware** the agent knows who's talking and where. It sees the user, the channel, and the interface so it can adjust tone, filter context, and keep track of different conversations within the same session.
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
- ## How it works
30
+ ## Dashboards
31
+
32
+ ![Agent dashboards](https://kern-ai.com/images/dashboards.png)
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
- TUI ──────────────┐
36
- Web UI ───────────┤
37
- Telegram DM ──────┤── kern ── one session ── one folder
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
- Every interface feeds into the same session. 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.
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
+ ![Memory UI — Segments](https://kern-ai.com/images/segments-2.png)
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
- ## Agent structure
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
- After `kern init`, your agent directory looks like:
56
+ ## One session
47
57
 
48
58
  ```
49
- my-agent/
50
- AGENTS.md # how the agent behaves (system prompt)
51
- IDENTITY.md # who the agent is
52
- KNOWLEDGE.md # index of what it knows
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
- Everything the agent needs is in this folder. Move it, zip it, clone it the agent comes with it. Run `kern init` on any existing repo to adopt it as a kern agent.
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 (auto-restart, boot persistence)
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|status> # static web UI server
76
- kern proxy <start|stop|status|token> # authenticated reverse proxy
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, web, and proxy status
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
- Agents auto-register when you init, start, or run them. `kern list` shows every agent, web, and proxy with running state and mode (systemd/daemon).
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 can connect to agents two ways:
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
- Agents bind to `0.0.0.0` on sticky ports (4100-4999), accessible over Tailscale or LAN. Add agents or remote proxy servers from the sidebar.
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
- ## User pairing
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
- ![Memory UI — Segments](https://kern-ai.com/images/segments-2.png)
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
- ## Logging
182
-
183
- ```bash
184
- kern logs [name] # follow logs (default)
185
- kern logs [name] -n 50 # last 50 lines, exit
186
- kern logs [name] --level warn # warnings and errors only
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
- Structured, leveled logs with colored labels. Stored in `.kern/logs/kern.log`. All levels written, filter on read.
111
+ First Telegram/Slack user is auto-paired as operator. Others pair with `KERN-XXXX` codes.
190
112
 
191
113
  ## Configuration
192
114
 
193
- ### Per-agent: `.kern/config.json`
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 (bash/pwsh), read, write, edit, glob, grep, webfetch, websearch, kern, message, recall
224
- - **write** — read, write, edit, glob, grep, webfetch, websearch, kern, message, recall
225
- - **read** — read, glob, grep, webfetch, websearch, kern, recall
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
- - **openrouter** any model via OpenRouter (default)
232
- - **anthropic** — direct Anthropic API
233
- - **openai** OpenAI / Azure
234
- - **ollama** local models via [Ollama](https://ollama.com)
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
- Detailed docs: [docs/](https://github.com/oguzbilgic/kern-ai/tree/master/docs)
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
 
@@ -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;AAoC9C;;;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"}
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": "kern-ai",
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":"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"}
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,YAAY;IACvB,oBAAoB,EAAE,YAAY;IAClC,yBAAyB,EAAE,0BAA0B;CACtD,CAAC;AAEF;;;GAGG;AACH,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,YAAY,EAAE,CAAC;QACxB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,wBAAwB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC3F,OAAO,YAAY,CAAC;gBAClB,OAAO,EAAE,GAAG,IAAI,KAAK;gBACrB,MAAM,EAAE,QAAQ;aACjB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,oEAAoE;YACpE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;YAC5E,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;YACzB,OAAO,YAAY,CAAC;gBAClB,OAAO,EAAE,8BAA8B;gBACvC,MAAM;gBACN,OAAO,EAAE,kBAAkB;aAC5B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO,MAAO,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;IACpD,CAAC;IAED,oDAAoD;IACpD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc;YAAE,OAAO,IAAI,CAAC;QAC7C,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;IACzD,CAAC;IAED,iEAAiE;IACjE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC5E,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC5C,CAAC,CAAC,+BAA+B;QACjC,CAAC,CAAC,wBAAwB,CAAC;IAC7B,OAAO,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,8DAA8D;AAC9D,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACrC,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClC;YACE,OAAO,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,8DAA8D;AAC9D,MAAM,UAAU,WAAW,CAAC,MAAkB;IAC5C,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;YACpC,OAAO,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,gFAAgF;YAChF,mFAAmF;YACnF,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC1C,MAAM,UAAU,GAAG,gBAAgB,CAAC;oBAClC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;oBACtC,OAAO,EAAE,kBAAkB;iBAC5B,CAAC,CAAC;gBACH,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,MAAM,GAAG,YAAY,CAAC;gBAC1B,OAAO,EAAE,8BAA8B;gBACvC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;gBACtC,OAAO,EAAE,kBAAkB;aAC5B,CAAC,CAAC;YACH,mEAAmE;YACnE,wEAAwE;YACxE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;YAC9B,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,wBAAwB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC3F,MAAM,MAAM,GAAG,YAAY,CAAC;gBAC1B,OAAO,EAAE,GAAG,IAAI,KAAK;gBACrB,MAAM,EAAE,QAAQ,EAAE,wCAAwC;aAC3D,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
@@ -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":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAgBnC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAe,CAAC;AAEpC,8EAA8E;AAC9E,MAAM,UAAU,OAAO,CAAC,QAAgB;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,MAAM,CAAC,GAAQ;IAC7B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,uBAAuB;AACvB,MAAM,UAAU,MAAM,CAAC,EAAU;IAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,6BAA6B;AAC7B,MAAM,UAAU,QAAQ;IACtB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,WAAW,CAAC,EAAU,EAAE,QAAuB;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzB,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,GAAG,CAAC,MAAM,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IAChD,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC1B,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,WAAW,CAAC,EAAU,EAAE,IAAmB;IACzD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzB,IAAI,GAAG;QAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC/B,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,sBAAsB,CAAC;QACxD,OAAO,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,sBAAsB,CAAC;IAChC,CAAC;AACH,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,KAAK,GAAG,EAAE;IACrD,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,sBAAsB,CAAC;QACxD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,kDAAkD;QAClD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAChE,QAAQ,CAAC,GAAG,EAAE,CAAC;QACjB,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,sBAAsB,CAAC;IAChC,CAAC;AACH,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,OAAO,CAAC;YAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;AACH,CAAC;AAQD,IAAI,cAAc,GAA0C,IAAI,CAAC;AAEjE,wDAAwD;AACxD,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,UAA6B,EAAE,UAAU,GAAG,IAAI;IAC1E,IAAI,cAAc;QAAE,OAAO,CAAC,kBAAkB;IAE9C,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;QAChC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAChC,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;gBAAE,SAAS;YACvC,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAEjC,wDAAwD;YACxD,8EAA8E;YAC9E,6CAA6C;YAC7C,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;YAElC,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtC,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,EAAE,mBAAmB,GAAG,CAAC,QAAQ,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;YACjG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,EAAE,UAAU,CAAC,CAAC;AACjB,CAAC;AAED,uBAAuB;AACvB,MAAM,UAAU,UAAU;IACxB,IAAI,cAAc,EAAE,CAAC;QACnB,aAAa,CAAC,cAAc,CAAC,CAAC;QAC9B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;AACH,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,WAAW;IACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,SAAS;QACvC,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACjC,GAAG,CAAC,MAAM,EAAE,uBAAuB,GAAG,CAAC,EAAE,SAAS,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { KernPlugin } from "../types.js";
2
+ export declare const execPlugin: KernPlugin;
3
+ //# sourceMappingURL=plugin.d.ts.map
@@ -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"}