atom-lite 0.0.0-stage → 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.
Files changed (175) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/LICENSE +21 -0
  3. package/README.md +265 -2
  4. package/dist/agent/loop.d.ts +30 -0
  5. package/dist/agent/loop.js +199 -0
  6. package/dist/agent/loop.js.map +1 -0
  7. package/dist/agent/types.d.ts +85 -0
  8. package/dist/agent/types.js +2 -0
  9. package/dist/agent/types.js.map +1 -0
  10. package/dist/cli/app.d.ts +1 -0
  11. package/dist/cli/app.js +1060 -0
  12. package/dist/cli/app.js.map +1 -0
  13. package/dist/cli/approvals.d.ts +1 -0
  14. package/dist/cli/approvals.js +2 -0
  15. package/dist/cli/approvals.js.map +1 -0
  16. package/dist/cli/banner.d.ts +8 -0
  17. package/dist/cli/banner.js +29 -0
  18. package/dist/cli/banner.js.map +1 -0
  19. package/dist/cli/commands.d.ts +19 -0
  20. package/dist/cli/commands.js +61 -0
  21. package/dist/cli/commands.js.map +1 -0
  22. package/dist/cli/main.d.ts +2 -0
  23. package/dist/cli/main.js +22 -0
  24. package/dist/cli/main.js.map +1 -0
  25. package/dist/cli/picker.d.ts +26 -0
  26. package/dist/cli/picker.js +175 -0
  27. package/dist/cli/picker.js.map +1 -0
  28. package/dist/cli/renderer.d.ts +1 -0
  29. package/dist/cli/renderer.js +5 -0
  30. package/dist/cli/renderer.js.map +1 -0
  31. package/dist/cli/secret-input.d.ts +21 -0
  32. package/dist/cli/secret-input.js +101 -0
  33. package/dist/cli/secret-input.js.map +1 -0
  34. package/dist/cli/status-line.d.ts +18 -0
  35. package/dist/cli/status-line.js +35 -0
  36. package/dist/cli/status-line.js.map +1 -0
  37. package/dist/cli/stream-text.d.ts +22 -0
  38. package/dist/cli/stream-text.js +50 -0
  39. package/dist/cli/stream-text.js.map +1 -0
  40. package/dist/cli/transcript.d.ts +17 -0
  41. package/dist/cli/transcript.js +40 -0
  42. package/dist/cli/transcript.js.map +1 -0
  43. package/dist/config/credentials.d.ts +26 -0
  44. package/dist/config/credentials.js +79 -0
  45. package/dist/config/credentials.js.map +1 -0
  46. package/dist/config/defaults.d.ts +24 -0
  47. package/dist/config/defaults.js +25 -0
  48. package/dist/config/defaults.js.map +1 -0
  49. package/dist/config/load.d.ts +7 -0
  50. package/dist/config/load.js +105 -0
  51. package/dist/config/load.js.map +1 -0
  52. package/dist/config/paths.d.ts +4 -0
  53. package/dist/config/paths.js +14 -0
  54. package/dist/config/paths.js.map +1 -0
  55. package/dist/config/schema.d.ts +83 -0
  56. package/dist/config/schema.js +52 -0
  57. package/dist/config/schema.js.map +1 -0
  58. package/dist/config/write.d.ts +18 -0
  59. package/dist/config/write.js +61 -0
  60. package/dist/config/write.js.map +1 -0
  61. package/dist/context/budget.d.ts +2 -0
  62. package/dist/context/budget.js +13 -0
  63. package/dist/context/budget.js.map +1 -0
  64. package/dist/context/compaction.d.ts +1 -0
  65. package/dist/context/compaction.js +5 -0
  66. package/dist/context/compaction.js.map +1 -0
  67. package/dist/context/instructions.d.ts +3 -0
  68. package/dist/context/instructions.js +30 -0
  69. package/dist/context/instructions.js.map +1 -0
  70. package/dist/context/manager.d.ts +29 -0
  71. package/dist/context/manager.js +122 -0
  72. package/dist/context/manager.js.map +1 -0
  73. package/dist/index.d.ts +16 -0
  74. package/dist/index.js +16 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/providers/catalog.d.ts +60 -0
  77. package/dist/providers/catalog.js +289 -0
  78. package/dist/providers/catalog.js.map +1 -0
  79. package/dist/providers/context-window.d.ts +11 -0
  80. package/dist/providers/context-window.js +87 -0
  81. package/dist/providers/context-window.js.map +1 -0
  82. package/dist/providers/factory.d.ts +2 -0
  83. package/dist/providers/factory.js +54 -0
  84. package/dist/providers/factory.js.map +1 -0
  85. package/dist/providers/fake.d.ts +14 -0
  86. package/dist/providers/fake.js +23 -0
  87. package/dist/providers/fake.js.map +1 -0
  88. package/dist/providers/gemini.d.ts +24 -0
  89. package/dist/providers/gemini.js +228 -0
  90. package/dist/providers/gemini.js.map +1 -0
  91. package/dist/providers/index.d.ts +5 -0
  92. package/dist/providers/index.js +4 -0
  93. package/dist/providers/index.js.map +1 -0
  94. package/dist/providers/ollama.d.ts +64 -0
  95. package/dist/providers/ollama.js +433 -0
  96. package/dist/providers/ollama.js.map +1 -0
  97. package/dist/providers/openai-compatible.d.ts +27 -0
  98. package/dist/providers/openai-compatible.js +282 -0
  99. package/dist/providers/openai-compatible.js.map +1 -0
  100. package/dist/providers/registry.d.ts +7 -0
  101. package/dist/providers/registry.js +13 -0
  102. package/dist/providers/registry.js.map +1 -0
  103. package/dist/providers/tool-calls.d.ts +18 -0
  104. package/dist/providers/tool-calls.js +42 -0
  105. package/dist/providers/tool-calls.js.map +1 -0
  106. package/dist/providers/types.d.ts +16 -0
  107. package/dist/providers/types.js +2 -0
  108. package/dist/providers/types.js.map +1 -0
  109. package/dist/runtime/approvals.d.ts +20 -0
  110. package/dist/runtime/approvals.js +20 -0
  111. package/dist/runtime/approvals.js.map +1 -0
  112. package/dist/runtime/locks.d.ts +13 -0
  113. package/dist/runtime/locks.js +180 -0
  114. package/dist/runtime/locks.js.map +1 -0
  115. package/dist/runtime/scheduler.d.ts +7 -0
  116. package/dist/runtime/scheduler.js +103 -0
  117. package/dist/runtime/scheduler.js.map +1 -0
  118. package/dist/security/paths.d.ts +1 -0
  119. package/dist/security/paths.js +35 -0
  120. package/dist/security/paths.js.map +1 -0
  121. package/dist/security/process.d.ts +1 -0
  122. package/dist/security/process.js +8 -0
  123. package/dist/security/process.js.map +1 -0
  124. package/dist/security/redaction.d.ts +1 -0
  125. package/dist/security/redaction.js +4 -0
  126. package/dist/security/redaction.js.map +1 -0
  127. package/dist/sessions/events.d.ts +21 -0
  128. package/dist/sessions/events.js +87 -0
  129. package/dist/sessions/events.js.map +1 -0
  130. package/dist/sessions/index.d.ts +3 -0
  131. package/dist/sessions/index.js +4 -0
  132. package/dist/sessions/index.js.map +1 -0
  133. package/dist/sessions/recovery.d.ts +6 -0
  134. package/dist/sessions/recovery.js +35 -0
  135. package/dist/sessions/recovery.js.map +1 -0
  136. package/dist/sessions/store.d.ts +91 -0
  137. package/dist/sessions/store.js +356 -0
  138. package/dist/sessions/store.js.map +1 -0
  139. package/dist/skills/registry.d.ts +23 -0
  140. package/dist/skills/registry.js +129 -0
  141. package/dist/skills/registry.js.map +1 -0
  142. package/dist/tools/bash.d.ts +2 -0
  143. package/dist/tools/bash.js +159 -0
  144. package/dist/tools/bash.js.map +1 -0
  145. package/dist/tools/diff.d.ts +7 -0
  146. package/dist/tools/diff.js +40 -0
  147. package/dist/tools/diff.js.map +1 -0
  148. package/dist/tools/edit.d.ts +2 -0
  149. package/dist/tools/edit.js +117 -0
  150. package/dist/tools/edit.js.map +1 -0
  151. package/dist/tools/index.d.ts +8 -0
  152. package/dist/tools/index.js +8 -0
  153. package/dist/tools/index.js.map +1 -0
  154. package/dist/tools/read.d.ts +2 -0
  155. package/dist/tools/read.js +138 -0
  156. package/dist/tools/read.js.map +1 -0
  157. package/dist/tools/registry.d.ts +7 -0
  158. package/dist/tools/registry.js +13 -0
  159. package/dist/tools/registry.js.map +1 -0
  160. package/dist/tools/types.d.ts +27 -0
  161. package/dist/tools/types.js +2 -0
  162. package/dist/tools/types.js.map +1 -0
  163. package/dist/tools/webfetch.d.ts +2 -0
  164. package/dist/tools/webfetch.js +97 -0
  165. package/dist/tools/webfetch.js.map +1 -0
  166. package/dist/tools/websearch.d.ts +2 -0
  167. package/dist/tools/websearch.js +88 -0
  168. package/dist/tools/websearch.js.map +1 -0
  169. package/dist/tools/write.d.ts +2 -0
  170. package/dist/tools/write.js +91 -0
  171. package/dist/tools/write.js.map +1 -0
  172. package/dist/types.d.ts +83 -0
  173. package/dist/types.js +10 -0
  174. package/dist/types.js.map +1 -0
  175. package/package.json +74 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-11-04
9
+
10
+ ### Added
11
+
12
+ - Local-first interactive TUI with streaming assistant output, thinking display,
13
+ boxed tool calls, and collapsible transcripts.
14
+ - Single agent loop with a conflict-aware tool scheduler.
15
+ - Built-in `read`, `write`, `edit`, `bash`, `webfetch`, and `websearch` tools.
16
+ - Provider adapters for OpenAI-compatible endpoints, Ollama, and Gemini.
17
+ - Interactive `/provider` setup with hidden API-key input and validation.
18
+ - Fuzzy `/model` picker spanning every configured provider.
19
+ - Durable JSONL sessions with resume support.
20
+ - Context management with compaction, project instructions, and skill indexing.
21
+ - Live context-window usage in the status line (`tokens: 4.5k/256k`).
22
+ - Bold-red ANSI Shadow startup banner.
23
+ - Approval modes, workspace path boundaries, and hash-guarded writes.
24
+ - Non-gating performance benchmark suite for tools, startup, and TUI rendering.
25
+
26
+ [0.1.0]: https://github.com/beast-ofcourse/atom-lite/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Atom-lite contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,266 @@
1
- # Temporary Holding Version
1
+ # Atom-lite
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![npm](https://img.shields.io/npm/v/atom-lite?logo=npm)](https://www.npmjs.com/package/atom-lite)
4
+ [![CI](https://github.com/beast-ofcourse/atom-lite/actions/workflows/ci.yml/badge.svg)](https://github.com/beast-ofcourse/atom-lite/actions/workflows/ci.yml)
5
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D22.19-339933?logo=node.js&logoColor=white)](https://nodejs.org)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
8
+
9
+ **Atom-lite** is a local-first, model-agnostic coding agent with an intentionally small harness: one agent loop, exactly four built-in tools (`read`, `write`, `edit`, `bash`), a deterministic conflict-aware scheduler, durable JSONL sessions, and explicit safety boundaries. It runs against local or hosted model providers through interchangeable adapters — no cloud account, telemetry service, or hosted control plane required.
10
+
11
+ > Working title: *ThinAgent*. See [`project-overview.md`](./project-overview.md) for the full architecture blueprint, [`GLOSSARY.md`](./GLOSSARY.md) for domain vocabulary, and [`docs/adr/`](./docs/adr/) for architectural decisions.
12
+
13
+ ---
14
+
15
+ ## Table of contents
16
+
17
+ - [Why Atom-lite](#why-atom-lite)
18
+ - [Features](#features)
19
+ - [Install](#install)
20
+ - [Quick start](#quick-start)
21
+ - [Default provider](#default-provider)
22
+ - [Configuration](#configuration)
23
+ - [Usage](#usage)
24
+ - [Tools](#tools)
25
+ - [Providers](#providers)
26
+ - [Safety & security](#safety--security)
27
+ - [Sessions](#sessions)
28
+ - [Context management](#context-management)
29
+ - [Development](#development)
30
+ - [Architecture](#architecture)
31
+ - [Contributing](#contributing)
32
+ - [License](#license)
33
+
34
+ ## Why Atom-lite
35
+
36
+ Most coding agents accumulate tools, sub-agents, planning frameworks, retrieval pipelines, and orchestration layers until the harness itself becomes the product. Atom-lite takes the opposite stance:
37
+
38
+ - **Small core, strong primitives.** The core contains only a provider interface, a session model, a single agent loop, four tools, a scheduler/executor, context-window management, configuration, and a CLI.
39
+ - **The model decides; the runtime enforces.** The model chooses which tool to call and what to do next. The runtime validates arguments, enforces workspace boundaries, applies approval rules, schedules calls safely, and returns accurate results. There is no hard-coded "plan → inspect → edit → test" workflow.
40
+ - **Thin harness, not weak engineering.** Provider-specific formats, streaming failures, concurrent file access, shell timeouts, large outputs, context exhaustion, and session recovery are all handled — they are the reliability layer that makes a small harness useful.
41
+
42
+ ## Features
43
+
44
+ - **Four general-purpose tools** — `read`, `write`, `edit`, `bash`. Everything else (search, tests, git, builds) goes through `bash`.
45
+ - **Single agent loop** — one agent, one conversation, one tool registry, one control loop. Parallelism lives inside a tool-call batch.
46
+ - **Conflict-aware scheduler** — per-file read/write locks and a global bash barrier. Parallelism is governed by resource conflicts, not applied blindly.
47
+ - **Durable sessions** — append-only JSONL event logs, resumable across CLI restarts, grouped by workspace.
48
+ - **Context management** — token estimation, compaction (summarization of older history) before the context budget is exceeded, while retaining the full transcript.
49
+ - **Live context meter** — the status line shows context tokens used against the selected model's real window (e.g. `tokens: 4.5k/256k`), resolved from provider metadata with known-model fallbacks.
50
+ - **Approval modes** — `ask` / `trusted` / `deny` for shell commands, with session-level trust.
51
+ - **Hash guards** — `expected_hash` rejects stale `write`/`edit` operations when the file changed since it was read.
52
+ - **Provider-agnostic** — Ollama, Gemini, and any OpenAI-compatible endpoint (LM Studio, llama.cpp, Kilo AI Gateway, OpenAI, Anthropic, OpenRouter, Groq, Mistral, xAI, …).
53
+ - **Interactive provider/model pickers** — `/provider` adds a provider and stores its key securely; `/model` fuzzy-searches every configured provider's models.
54
+ - **Local-first** — runs fully against local providers with no cloud account, telemetry, or hosted database.
55
+ - **Safe path handling** — file tools resolve against the workspace and reject escapes; shell is an explicit, sandbox-aware boundary.
56
+
57
+ ## Install
58
+
59
+ ```sh
60
+ npm install -g atom-lite
61
+ ```
62
+
63
+ Or run without installing:
64
+
65
+ ```sh
66
+ npx atom-lite "fix the failing test"
67
+ ```
68
+
69
+ Requires **Node.js >= 22.19** (see `engines` in `package.json`).
70
+
71
+ ## Quick start
72
+
73
+ ```sh
74
+ atom-lite # interactive session in the current directory
75
+ atom-lite "task" # run one task, then exit
76
+ atom-lite --provider NAME # select a provider profile
77
+ atom-lite --continue # resume the most recent session
78
+ atom-lite --help
79
+ ```
80
+
81
+ Pipe a task via stdin:
82
+
83
+ ```sh
84
+ echo "summarize this repo" | atom-lite
85
+ ```
86
+
87
+ ## Default provider
88
+
89
+ Out of the box, Atom-lite uses the **Kilo AI Gateway** (`https://api.kilo.ai/api/gateway`) with the free `kilo-auto/free` model. No API key is required (rate-limited to 200 requests/hour per IP for anonymous use). Override via `--provider`/`--model` or config.
90
+
91
+ ## Configuration
92
+
93
+ User config: `~/.config/atom-lite/config.json`
94
+ Project config: `.atom-lite/config.json` (non-secrets only)
95
+
96
+ Precedence (low → high): defaults → user config → project config (non-secret) → environment → CLI overrides. Security-critical user settings (e.g. `approvalMode`) are **not** overridable by project config.
97
+
98
+ Secrets are stored in `~/.config/atom-lite/credentials.json` with owner-only permissions (`0600`). Environment variables named by a provider's `apiKeyEnv` take precedence over the stored key. Secrets are never written to project config or session files.
99
+
100
+ Environment overrides:
101
+
102
+ | Variable | Effect |
103
+ | --- | --- |
104
+ | `ATOM_LITE_PROVIDER` | Default provider profile name |
105
+ | `ATOM_LITE_APPROVAL_MODE` | `ask` / `trusted` / `deny` |
106
+
107
+ Example `config.json`:
108
+
109
+ ```json
110
+ {
111
+ "defaultProvider": "kilo",
112
+ "providers": {
113
+ "kilo": {
114
+ "type": "openai-compatible",
115
+ "baseUrl": "https://api.kilo.ai/api/gateway",
116
+ "model": "kilo-auto/free",
117
+ "apiKeyEnv": null
118
+ },
119
+ "ollama": {
120
+ "type": "ollama",
121
+ "baseUrl": "http://127.0.0.1:11434",
122
+ "model": "qwen2.5-coder:7b"
123
+ },
124
+ "gemini": {
125
+ "type": "gemini",
126
+ "model": "gemini-2.0-flash",
127
+ "apiKeyEnv": "GEMINI_API_KEY"
128
+ }
129
+ },
130
+ "runtime": {
131
+ "approvalMode": "ask",
132
+ "bashConcurrency": "serial",
133
+ "maxIterations": 40,
134
+ "maxToolCalls": 100
135
+ },
136
+ "context": {
137
+ "maxInputTokens": null,
138
+ "reserveOutputTokens": 4096,
139
+ "compactAtPercent": 85
140
+ }
141
+ }
142
+ ```
143
+
144
+ See [`project-overview.md`](./project-overview.md) for the full configuration shape.
145
+
146
+ ## Usage
147
+
148
+ ```
149
+ atom-lite [task] [--provider NAME] [--model MODEL] [--continue] [--session ID]
150
+ [--no-tools] [--json] [--debug] [--version] [--help]
151
+ ```
152
+
153
+ | Flag | Description |
154
+ | --- | --- |
155
+ | `task` | One-shot task; agent runs it and exits |
156
+ | `--provider NAME` | Select a provider profile |
157
+ | `--model MODEL` | Override the model for this run |
158
+ | `--continue` | Resume the most recent session in this workspace |
159
+ | `--session ID` | Resume a specific session |
160
+ | `--no-tools` | Disable all tools (model-only chat) |
161
+ | `--json` | Non-interactive JSON output |
162
+ | `--debug` | Debug logging |
163
+ | `--version` | Print version |
164
+ | `--help` | Show help |
165
+
166
+ ## Tools
167
+
168
+ Four core tools (see [ADR 0001](./docs/adr/0001-four-built-in-tools-only.md)) plus the additive network tools from [ADR 0006](./docs/adr/0006-expanded-toolset.md):
169
+
170
+ | Tool | Purpose |
171
+ | --- | --- |
172
+ | `read` | Inspect files (with optional line ranges) |
173
+ | `write` | Create or replace files safely (hash-guarded) |
174
+ | `edit` | Precise find-and-replace edits (hash-guarded) |
175
+ | `bash` | Execute shell commands (global exclusive barrier by default) |
176
+ | `webfetch` | Fetch a URL and convert HTML to markdown |
177
+ | `websearch` | Search the web and return ranked results |
178
+
179
+ File discovery, search, tests, Git, builds, formatters, and package managers are available through `bash`, not through additional built-in tools.
180
+
181
+ ## Providers
182
+
183
+ | Type | Adapter | Notes |
184
+ | --- | --- | --- |
185
+ | `openai-compatible` | `OpenAICompatibleAdapter` | LM Studio, llama.cpp/llama-server, Kilo AI Gateway, and other compatible endpoints |
186
+ | `ollama` | `OllamaAdapter` | Native Ollama chat API |
187
+ | `gemini` | `GeminiAdapter` | Official Gemini API |
188
+
189
+ Provider profiles are named combinations of endpoint, model, auth source, and options. Switching profiles mid-tool-exchange is disallowed.
190
+
191
+ ### Interactive setup
192
+
193
+ - `/provider` opens a searchable list of built-in providers (Kilo, OpenAI, Anthropic, Google Gemini, OpenRouter, Groq, Mistral, xAI, Ollama, LM Studio, llama.cpp). Selecting a hosted provider prompts for an API key with hidden input, validates it against the provider, and saves it to `~/.config/atom-lite/credentials.json` (`0600`).
194
+ - `/model` opens a fuzzy-searchable picker containing models from **every configured provider** (plus providers whose key is present in the environment). Live model lists are fetched in the background while the picker stays responsive.
195
+ - `/model <provider>/<model>` and `/provider <name>` are the non-interactive forms.
196
+
197
+ The selected provider/model is persisted to the user config, so the next session starts where you left off.
198
+
199
+ ## Safety & security
200
+
201
+ - **Workspace boundary** — `read`/`write`/`edit` resolve paths against the workspace and reject escapes. Shell commands are not constrained by this boundary (their effects are unknown), so `bash` runs as a global exclusive barrier.
202
+ - **Approval modes** — `ask` prompts before each shell command; `trusted` auto-approves; `deny` blocks. Session trust can be granted interactively (`t`).
203
+ - **Hash guards** — prevent stale overwrites when a file changed since it was read.
204
+ - **Sandboxing flags** — reported per command; see `src/security/`.
205
+ - **No secrets in config** — interactive provider setup stores API keys in `~/.config/atom-lite/credentials.json` with `0600` permissions; environment variables still take precedence.
206
+ - **Local-first** — no cloud account, telemetry, or remote control plane required (see [ADR 0004](./docs/adr/0004-local-first-no-cloud-dependency.md)).
207
+
208
+ ## Sessions
209
+
210
+ Sessions are append-only JSONL event logs recording everything that happened in one conversation. They are resumable across CLI restarts and grouped by workspace. Stored under the session store (see `src/sessions/`). Compaction summarizes older history to stay within the context budget while retaining the full transcript.
211
+
212
+ ## Context management
213
+
214
+ The context manager builds model input, estimates tokens, and triggers compaction before the context budget is exceeded. It also loads project instructions (e.g. `AGENTS.md`/`CLAUDE.md`-style files) subject to `maxProjectInstructionBytes`.
215
+
216
+ ## Development
217
+
218
+ ```sh
219
+ npm install
220
+ npm run dev # run via tsx (src/cli/main.ts)
221
+ npm start # build and run
222
+ npm run typecheck # tsc --noEmit
223
+ npm test # build + node --test
224
+ npm run build # tsc
225
+ npm run format # prettier --write .
226
+ ```
227
+
228
+ Tests live in `tests/` (agent, config, runtime, tools). The project is TypeScript (strict) on NodeNext ESM.
229
+
230
+ ### Releasing
231
+
232
+ 1. Update `version` in `package.json` and add a `CHANGELOG.md` entry.
233
+ 2. Run `npm run typecheck && npm test && npm run bench`.
234
+ 3. Commit, then tag and push: `git tag vX.Y.Z && git push origin master --tags`.
235
+ 4. The `Release` GitHub workflow publishes to npm with provenance and creates the GitHub release. It requires an `NPM_TOKEN` repository secret with publish access.
236
+
237
+ ## Architecture
238
+
239
+ ```
240
+ src/
241
+ agent/ # agent loop & types
242
+ cli/ # terminal UI, approvals, commands
243
+ config/ # schema, defaults, loader
244
+ context/ # builder, manager, compaction, budget, instructions
245
+ providers/ # adapters (openai-compatible, ollama, gemini, fake) + factory
246
+ runtime/ # scheduler, approvals
247
+ security/ # paths, process, redaction
248
+ sessions/ # store, events, recovery
249
+ tools/ # read, write, edit, bash, registry
250
+ ```
251
+
252
+ Key design decisions are recorded as ADRs in [`docs/adr/`](./docs/adr/):
253
+
254
+ - [0001 — Four built-in tools only](./docs/adr/0001-four-built-in-tools-only.md)
255
+ - [0002 — Single agent loop, no sub-agents in v1](./docs/adr/0002-single-agent-loop.md)
256
+ - [0003 — `bash` is a global exclusive barrier](./docs/adr/0003-bash-as-global-exclusive-barrier.md)
257
+ - [0004 — Local-first, no cloud dependency](./docs/adr/0004-local-first-no-cloud-dependency.md)
258
+ - [0005 — OpenTUI for the terminal UI](./docs/adr/0005-opentui-for-terminal-ui.md)
259
+
260
+ ## Contributing
261
+
262
+ Issues and specs live as markdown under `.scratch/` (see [`docs/agents/issue-tracker.md`](./docs/agents/issue-tracker.md)). Domain vocabulary is in [`GLOSSARY.md`](./GLOSSARY.md). Please keep changes consistent with the "small core" principle: new tools require strong justification against ADR 0001.
263
+
264
+ ## License
265
+
266
+ MIT
@@ -0,0 +1,30 @@
1
+ import type { AgentRuntimeOptions, ContextUsage } from "./types.js";
2
+ import type { Message } from "../types.js";
3
+ export declare class AgentRuntime {
4
+ private provider;
5
+ private model;
6
+ private workspace;
7
+ private approvals;
8
+ private contextManager;
9
+ private onEvent;
10
+ private tools;
11
+ private effort;
12
+ private bashConcurrency;
13
+ private toolMap;
14
+ private limits;
15
+ private systemPrompt;
16
+ private contextWindow;
17
+ private contextUsed;
18
+ constructor(options: AgentRuntimeOptions);
19
+ switchModel(provider: AgentRuntimeOptions["provider"], model?: string): void;
20
+ /** Update the context window for the selected model (metadata may arrive late). */
21
+ setContextWindow(window: number | undefined): void;
22
+ getContextUsage(): ContextUsage;
23
+ private emitContextUsage;
24
+ setEffort(effort: string): void;
25
+ getEffort(): string;
26
+ runAgentTurn(input: string, session: {
27
+ messages: Message[];
28
+ appendMessage(m: Message): void;
29
+ }, signal: AbortSignal): Promise<string>;
30
+ }
@@ -0,0 +1,199 @@
1
+ import { DEFAULT_LIMITS } from "../types.js";
2
+ import { executeToolBatch } from "../runtime/scheduler.js";
3
+ import { ContextManager } from "../context/manager.js";
4
+ export class AgentRuntime {
5
+ provider;
6
+ model;
7
+ workspace;
8
+ approvals;
9
+ contextManager;
10
+ onEvent;
11
+ tools;
12
+ effort;
13
+ bashConcurrency;
14
+ toolMap;
15
+ limits;
16
+ systemPrompt;
17
+ contextWindow;
18
+ contextUsed;
19
+ constructor(options) {
20
+ this.provider = options.provider;
21
+ this.model = options.model ?? "default";
22
+ this.workspace = options.workspace ?? process.cwd();
23
+ this.approvals = options.approvals;
24
+ this.onEvent = options.onEvent;
25
+ this.tools = options.tools;
26
+ this.effort = options.effort ?? "medium";
27
+ this.bashConcurrency = options.bashConcurrency ?? "serial";
28
+ this.contextManager =
29
+ options.contextManager ??
30
+ new ContextManager({
31
+ systemPrompt: options.systemPrompt ?? "You are a coding assistant.",
32
+ maxInputTokens: null,
33
+ reserveOutputTokens: 4096,
34
+ compactAtPercent: 85,
35
+ maxProjectInstructionBytes: 30000,
36
+ provider: options.provider,
37
+ model: options.model ?? "default",
38
+ });
39
+ this.toolMap = new Map(options.tools.map((t) => [t.definition.name, t]));
40
+ this.limits = { ...DEFAULT_LIMITS, ...(options.limits ?? {}) };
41
+ this.systemPrompt = options.systemPrompt ?? "You are a coding assistant with tools: read, write, edit, bash, webfetch, websearch.";
42
+ this.contextWindow = options.contextWindow;
43
+ this.contextManager.setModelContextWindow(options.contextWindow);
44
+ }
45
+ switchModel(provider, model) {
46
+ this.provider = provider;
47
+ if (model)
48
+ this.model = model;
49
+ this.contextManager.setProvider(provider, this.model);
50
+ // The new model has a fresh window; usage from the old one is meaningless.
51
+ this.contextUsed = undefined;
52
+ this.onEvent?.({ type: "model_switched", provider: provider.id, model: this.model });
53
+ this.emitContextUsage();
54
+ }
55
+ /** Update the context window for the selected model (metadata may arrive late). */
56
+ setContextWindow(window) {
57
+ const next = typeof window === "number" && Number.isFinite(window) && window > 0
58
+ ? Math.floor(window)
59
+ : undefined;
60
+ if (next === this.contextWindow)
61
+ return;
62
+ this.contextWindow = next;
63
+ this.contextManager.setModelContextWindow(next);
64
+ this.emitContextUsage();
65
+ }
66
+ getContextUsage() {
67
+ return { used: this.contextUsed, window: this.contextWindow };
68
+ }
69
+ emitContextUsage() {
70
+ this.onEvent?.({
71
+ type: "context_usage",
72
+ used: this.contextUsed,
73
+ window: this.contextWindow,
74
+ });
75
+ }
76
+ setEffort(effort) {
77
+ this.effort = effort;
78
+ }
79
+ getEffort() {
80
+ return this.effort;
81
+ }
82
+ async runAgentTurn(input, session, signal) {
83
+ session.appendMessage({ role: "user", content: [{ type: "text", text: input }] });
84
+ let totalToolCalls = 0;
85
+ const start = Date.now();
86
+ for (let iteration = 0; iteration < this.limits.maxIterations; iteration++) {
87
+ if (signal.aborted) {
88
+ throw new Error("USER_CANCELLED");
89
+ }
90
+ if (Date.now() - start > this.limits.maxExecutionMs) {
91
+ return "TASK_BUDGET_REACHED";
92
+ }
93
+ const messages = await this.contextManager.build(this.workspace, session.messages);
94
+ if (this.contextManager.consumeCompaction()) {
95
+ // Peers treat usage as unknown after compaction until the next
96
+ // assistant response reports fresh numbers.
97
+ this.contextUsed = undefined;
98
+ this.emitContextUsage();
99
+ }
100
+ const request = {
101
+ model: this.model,
102
+ messages,
103
+ tools: this.tools.map((t) => t.definition),
104
+ signal,
105
+ options: { effort: this.effort },
106
+ };
107
+ let response;
108
+ let streamedText = "";
109
+ if (typeof this.provider.stream === "function") {
110
+ // Stream tokens as they arrive.
111
+ for await (const ev of this.provider.stream(request)) {
112
+ if (ev.type === "thinking") {
113
+ this.onEvent?.({ type: "thinking_delta", text: ev.text });
114
+ }
115
+ else if (ev.type === "text") {
116
+ streamedText += ev.text;
117
+ this.onEvent?.({ type: "assistant_delta", text: ev.text });
118
+ }
119
+ else if (ev.type === "done") {
120
+ response = ev.response;
121
+ }
122
+ }
123
+ if (!response) {
124
+ // Fallback if stream ended without done
125
+ response = {
126
+ message: { role: "assistant", content: streamedText ? [{ type: "text", text: streamedText }] : undefined, toolCalls: undefined },
127
+ toolCalls: [],
128
+ finishReason: "stop",
129
+ };
130
+ }
131
+ }
132
+ else {
133
+ response = await this.provider.generate(request);
134
+ const t = response.message.content?.map((p) => (p.type === "text" ? p.text : "")).join("") ?? "";
135
+ if (t)
136
+ this.onEvent?.({ type: "assistant_text", text: t });
137
+ streamedText = t;
138
+ }
139
+ session.appendMessage(response.message);
140
+ if (response.usage) {
141
+ this.onEvent?.({ type: "usage", input: response.usage.input, output: response.usage.output });
142
+ const used = (response.usage.input ?? 0) + (response.usage.output ?? 0);
143
+ if (used > 0) {
144
+ // The latest assistant step's prompt + generated tokens is the
145
+ // current context occupancy (not a cumulative session total).
146
+ this.contextUsed = used;
147
+ this.emitContextUsage();
148
+ }
149
+ }
150
+ const text = streamedText || (response.message.content?.map((p) => (p.type === "text" ? p.text : "")).join("") ?? "");
151
+ const toolCalls = response.toolCalls ?? [];
152
+ if (toolCalls.length === 0) {
153
+ this.onEvent?.({ type: "final", text });
154
+ return text;
155
+ }
156
+ for (const c of toolCalls)
157
+ this.onEvent?.({ type: "tool_call", id: c.id, name: c.name, args: c.arguments });
158
+ totalToolCalls += toolCalls.length;
159
+ if (totalToolCalls > this.limits.maxToolCalls) {
160
+ return "TASK_BUDGET_REACHED";
161
+ }
162
+ const ctx = {
163
+ workspace: this.workspace,
164
+ signal,
165
+ maxBashTimeMs: this.limits.maxBashTimeMs,
166
+ maxToolOutputBytes: this.limits.maxToolOutputBytes,
167
+ approvals: this.approvals,
168
+ onToolOutput: (call, stream, text) => {
169
+ this.onEvent?.({
170
+ type: "tool_output",
171
+ toolCallId: call.id,
172
+ name: call.name,
173
+ stream,
174
+ text,
175
+ });
176
+ },
177
+ };
178
+ const results = await executeToolBatch(toolCalls, this.toolMap, ctx, this.limits.maxParallelToolCalls, signal, undefined, this.bashConcurrency);
179
+ for (const r of results) {
180
+ session.appendMessage({
181
+ role: "tool",
182
+ toolCallId: r.toolCallId,
183
+ name: r.name,
184
+ content: r.content,
185
+ });
186
+ this.onEvent?.({
187
+ type: "tool_result",
188
+ toolCallId: r.toolCallId,
189
+ name: r.name,
190
+ content: r.content,
191
+ isError: r.isError,
192
+ diff: r.diff,
193
+ });
194
+ }
195
+ }
196
+ return "TASK_BUDGET_REACHED";
197
+ }
198
+ }
199
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import type { AgentLimits } from "../types.js";
2
+ export type { AgentLimits };
3
+ import type { Message } from "../types.js";
4
+ import type { ProviderAdapter } from "../providers/types.js";
5
+ import type { Tool } from "../tools/types.js";
6
+ import type { ApprovalContext } from "../runtime/approvals.js";
7
+ import type { ContextManager } from "../context/manager.js";
8
+ export type AgentEvent = {
9
+ type: "assistant_delta";
10
+ text: string;
11
+ } | {
12
+ type: "thinking_delta";
13
+ text: string;
14
+ } | {
15
+ type: "assistant_text";
16
+ text: string;
17
+ } | {
18
+ type: "tool_call";
19
+ id: string;
20
+ name: string;
21
+ args: Record<string, unknown>;
22
+ } | {
23
+ type: "tool_output";
24
+ toolCallId: string;
25
+ name: string;
26
+ stream: "stdout" | "stderr";
27
+ text: string;
28
+ } | {
29
+ type: "tool_result";
30
+ toolCallId: string;
31
+ name: string;
32
+ content: string;
33
+ isError?: boolean;
34
+ diff?: string[];
35
+ } | {
36
+ type: "final";
37
+ text: string;
38
+ } | {
39
+ type: "usage";
40
+ input?: number;
41
+ output?: number;
42
+ } | {
43
+ type: "context_usage";
44
+ used?: number;
45
+ window?: number;
46
+ } | {
47
+ type: "model_switched";
48
+ provider: string;
49
+ model: string;
50
+ } | {
51
+ type: "skill_loaded";
52
+ name: string;
53
+ } | {
54
+ type: "error";
55
+ message: string;
56
+ };
57
+ export interface AgentRuntimeOptions {
58
+ provider: ProviderAdapter;
59
+ model?: string;
60
+ workspace?: string;
61
+ tools: Tool[];
62
+ limits?: Partial<AgentLimits>;
63
+ systemPrompt?: string;
64
+ approvals?: ApprovalContext;
65
+ contextManager?: ContextManager;
66
+ onEvent?: (event: AgentEvent) => void;
67
+ effort?: string;
68
+ bashConcurrency?: "serial" | "parallel";
69
+ /** Selected model's context window, when known. */
70
+ contextWindow?: number;
71
+ }
72
+ export interface ContextUsage {
73
+ /** Tokens occupied after the latest assistant response, when known. */
74
+ used?: number;
75
+ /** Selected model's context window, when known. */
76
+ window?: number;
77
+ }
78
+ export interface RunTurnParams {
79
+ input: string;
80
+ session: {
81
+ messages: Message[];
82
+ append(m: Message): void;
83
+ };
84
+ signal: AbortSignal;
85
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export declare function run(args: string[]): Promise<void>;