atom-lite 0.0.0-stage → 0.4.1
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/CHANGELOG.md +72 -0
- package/LICENSE +21 -0
- package/README.md +313 -2
- package/dist/agent/loop.d.ts +32 -0
- package/dist/agent/loop.js +204 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/types.d.ts +85 -0
- package/dist/agent/types.js +2 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/activity.d.ts +45 -0
- package/dist/cli/activity.js +141 -0
- package/dist/cli/activity.js.map +1 -0
- package/dist/cli/app.d.ts +1 -0
- package/dist/cli/app.js +1576 -0
- package/dist/cli/app.js.map +1 -0
- package/dist/cli/approval-prompt.d.ts +24 -0
- package/dist/cli/approval-prompt.js +82 -0
- package/dist/cli/approval-prompt.js.map +1 -0
- package/dist/cli/approvals.d.ts +1 -0
- package/dist/cli/approvals.js +2 -0
- package/dist/cli/approvals.js.map +1 -0
- package/dist/cli/banner.d.ts +12 -0
- package/dist/cli/banner.js +35 -0
- package/dist/cli/banner.js.map +1 -0
- package/dist/cli/commands.d.ts +94 -0
- package/dist/cli/commands.js +324 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/diff.d.ts +1 -0
- package/dist/cli/diff.js +28 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli/input.d.ts +2 -0
- package/dist/cli/input.js +10 -0
- package/dist/cli/input.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +22 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/mouse.d.ts +54 -0
- package/dist/cli/mouse.js +83 -0
- package/dist/cli/mouse.js.map +1 -0
- package/dist/cli/palette.d.ts +41 -0
- package/dist/cli/palette.js +212 -0
- package/dist/cli/palette.js.map +1 -0
- package/dist/cli/panel.d.ts +29 -0
- package/dist/cli/panel.js +48 -0
- package/dist/cli/panel.js.map +1 -0
- package/dist/cli/picker.d.ts +34 -0
- package/dist/cli/picker.js +173 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/renderer.d.ts +1 -0
- package/dist/cli/renderer.js +5 -0
- package/dist/cli/renderer.js.map +1 -0
- package/dist/cli/secret-input.d.ts +21 -0
- package/dist/cli/secret-input.js +101 -0
- package/dist/cli/secret-input.js.map +1 -0
- package/dist/cli/status-line.d.ts +24 -0
- package/dist/cli/status-line.js +49 -0
- package/dist/cli/status-line.js.map +1 -0
- package/dist/cli/stream-text.d.ts +18 -0
- package/dist/cli/stream-text.js +63 -0
- package/dist/cli/stream-text.js.map +1 -0
- package/dist/cli/theme.d.ts +48 -0
- package/dist/cli/theme.js +158 -0
- package/dist/cli/theme.js.map +1 -0
- package/dist/cli/tool-box.d.ts +41 -0
- package/dist/cli/tool-box.js +177 -0
- package/dist/cli/tool-box.js.map +1 -0
- package/dist/cli/transcript.d.ts +26 -0
- package/dist/cli/transcript.js +64 -0
- package/dist/cli/transcript.js.map +1 -0
- package/dist/config/credentials.d.ts +26 -0
- package/dist/config/credentials.js +79 -0
- package/dist/config/credentials.js.map +1 -0
- package/dist/config/defaults.d.ts +34 -0
- package/dist/config/defaults.js +35 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/load.d.ts +9 -0
- package/dist/config/load.js +137 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/paths.d.ts +4 -0
- package/dist/config/paths.js +14 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/schema.d.ts +132 -0
- package/dist/config/schema.js +83 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/write.d.ts +20 -0
- package/dist/config/write.js +70 -0
- package/dist/config/write.js.map +1 -0
- package/dist/context/budget.d.ts +2 -0
- package/dist/context/budget.js +13 -0
- package/dist/context/budget.js.map +1 -0
- package/dist/context/builder.d.ts +7 -0
- package/dist/context/builder.js +11 -0
- package/dist/context/builder.js.map +1 -0
- package/dist/context/compaction.d.ts +1 -0
- package/dist/context/compaction.js +5 -0
- package/dist/context/compaction.js.map +1 -0
- package/dist/context/instructions.d.ts +3 -0
- package/dist/context/instructions.js +30 -0
- package/dist/context/instructions.js.map +1 -0
- package/dist/context/manager.d.ts +29 -0
- package/dist/context/manager.js +122 -0
- package/dist/context/manager.js.map +1 -0
- package/dist/extensions/api.d.ts +51 -0
- package/dist/extensions/api.js +101 -0
- package/dist/extensions/api.js.map +1 -0
- package/dist/extensions/discovery.d.ts +26 -0
- package/dist/extensions/discovery.js +243 -0
- package/dist/extensions/discovery.js.map +1 -0
- package/dist/extensions/loader.d.ts +27 -0
- package/dist/extensions/loader.js +113 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/trust.d.ts +4 -0
- package/dist/extensions/trust.js +40 -0
- package/dist/extensions/trust.js.map +1 -0
- package/dist/extensions/types.d.ts +52 -0
- package/dist/extensions/types.js +2 -0
- package/dist/extensions/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +73 -0
- package/dist/mcp/client.js +363 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/format.d.ts +3 -0
- package/dist/mcp/format.js +37 -0
- package/dist/mcp/format.js.map +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +7 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/manager.d.ts +53 -0
- package/dist/mcp/manager.js +349 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/mcp/stdio-transport.d.ts +26 -0
- package/dist/mcp/stdio-transport.js +191 -0
- package/dist/mcp/stdio-transport.js.map +1 -0
- package/dist/mcp/tools.d.ts +22 -0
- package/dist/mcp/tools.js +162 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/types.d.ts +92 -0
- package/dist/mcp/types.js +2 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/providers/catalog.d.ts +60 -0
- package/dist/providers/catalog.js +289 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/context-window.d.ts +11 -0
- package/dist/providers/context-window.js +87 -0
- package/dist/providers/context-window.js.map +1 -0
- package/dist/providers/factory.d.ts +2 -0
- package/dist/providers/factory.js +55 -0
- package/dist/providers/factory.js.map +1 -0
- package/dist/providers/fake.d.ts +14 -0
- package/dist/providers/fake.js +23 -0
- package/dist/providers/fake.js.map +1 -0
- package/dist/providers/gemini.d.ts +24 -0
- package/dist/providers/gemini.js +228 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.js +4 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.d.ts +64 -0
- package/dist/providers/ollama.js +433 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +27 -0
- package/dist/providers/openai-compatible.js +282 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/providers/registry.d.ts +7 -0
- package/dist/providers/registry.js +13 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/tool-calls.d.ts +18 -0
- package/dist/providers/tool-calls.js +42 -0
- package/dist/providers/tool-calls.js.map +1 -0
- package/dist/providers/types.d.ts +16 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/runtime/approvals.d.ts +20 -0
- package/dist/runtime/approvals.js +20 -0
- package/dist/runtime/approvals.js.map +1 -0
- package/dist/runtime/executor.d.ts +2 -0
- package/dist/runtime/executor.js +4 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/runtime/locks.d.ts +13 -0
- package/dist/runtime/locks.js +180 -0
- package/dist/runtime/locks.js.map +1 -0
- package/dist/runtime/scheduler.d.ts +7 -0
- package/dist/runtime/scheduler.js +110 -0
- package/dist/runtime/scheduler.js.map +1 -0
- package/dist/security/paths.d.ts +1 -0
- package/dist/security/paths.js +35 -0
- package/dist/security/paths.js.map +1 -0
- package/dist/security/process.d.ts +1 -0
- package/dist/security/process.js +8 -0
- package/dist/security/process.js.map +1 -0
- package/dist/security/redaction.d.ts +1 -0
- package/dist/security/redaction.js +4 -0
- package/dist/security/redaction.js.map +1 -0
- package/dist/sessions/events.d.ts +30 -0
- package/dist/sessions/events.js +92 -0
- package/dist/sessions/events.js.map +1 -0
- package/dist/sessions/history.d.ts +18 -0
- package/dist/sessions/history.js +76 -0
- package/dist/sessions/history.js.map +1 -0
- package/dist/sessions/index.d.ts +5 -0
- package/dist/sessions/index.js +6 -0
- package/dist/sessions/index.js.map +1 -0
- package/dist/sessions/recovery.d.ts +6 -0
- package/dist/sessions/recovery.js +35 -0
- package/dist/sessions/recovery.js.map +1 -0
- package/dist/sessions/search.d.ts +16 -0
- package/dist/sessions/search.js +136 -0
- package/dist/sessions/search.js.map +1 -0
- package/dist/sessions/store.d.ts +91 -0
- package/dist/sessions/store.js +360 -0
- package/dist/sessions/store.js.map +1 -0
- package/dist/skills/registry.d.ts +23 -0
- package/dist/skills/registry.js +129 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/tools/bash.d.ts +2 -0
- package/dist/tools/bash.js +159 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/diff.d.ts +7 -0
- package/dist/tools/diff.js +40 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +118 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/read.d.ts +2 -0
- package/dist/tools/read.js +138 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/registry.d.ts +7 -0
- package/dist/tools/registry.js +13 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +27 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/webfetch.d.ts +2 -0
- package/dist/tools/webfetch.js +97 -0
- package/dist/tools/webfetch.js.map +1 -0
- package/dist/tools/websearch.d.ts +2 -0
- package/dist/tools/websearch.js +88 -0
- package/dist/tools/websearch.js.map +1 -0
- package/dist/tools/write.d.ts +2 -0
- package/dist/tools/write.js +91 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +74 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
## [0.4.1] - 2026-11-04
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- npm publish retry after staged 0.4.0 conflict.
|
|
17
|
+
|
|
18
|
+
## [0.4.0] - 2026-11-04
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Extension discovery and manifest parsing (`src/extensions/discovery.ts`).
|
|
23
|
+
- Project trust gating and extension loader lifecycle with `/extensions`.
|
|
24
|
+
- `/export` for sessions.
|
|
25
|
+
- Markdown rendering for assistant responses and unified diff summaries in tool boxes.
|
|
26
|
+
- Literal edit replacement handling.
|
|
27
|
+
- Escape to cancel an active turn.
|
|
28
|
+
- TUI mouse capture fixes.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- Mouse capture sequence and startup ordering for TUI mouse support.
|
|
33
|
+
|
|
34
|
+
[0.4.0]: https://github.com/beast-ofcourse/atom-lite/releases/tag/v0.4.0
|
|
35
|
+
|
|
36
|
+
## [0.3.1] - 2026-11-04
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- MCP client over stdio: user-config-only `mcpServers`, lazy connections, tool
|
|
41
|
+
discovery and execution as `mcp__<server>__<tool>`, refresh on
|
|
42
|
+
`tools/list_changed`, `/mcp` and `/mcp reconnect`, and `/doctor` health.
|
|
43
|
+
- Session picker and search (`/sessions`, `/search`), resume in place, and
|
|
44
|
+
`/session rename`.
|
|
45
|
+
- Command palette (`ctrl+p`), semantic theme registry, and TUI mouse support.
|
|
46
|
+
- Configuration reference and documentation index.
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- Ollama provider profiles now forward the `think` option to the adapter.
|
|
51
|
+
|
|
52
|
+
[0.3.1]: https://github.com/beast-ofcourse/atom-lite/releases/tag/v0.3.1
|
|
53
|
+
|
|
54
|
+
## [0.1.0] - 2026-11-04
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- Local-first interactive TUI with streaming assistant output, thinking display,
|
|
59
|
+
boxed tool calls, and collapsible transcripts.
|
|
60
|
+
- Single agent loop with a conflict-aware tool scheduler.
|
|
61
|
+
- Built-in `read`, `write`, `edit`, `bash`, `webfetch`, and `websearch` tools.
|
|
62
|
+
- Provider adapters for OpenAI-compatible endpoints, Ollama, and Gemini.
|
|
63
|
+
- Interactive `/provider` setup with hidden API-key input and validation.
|
|
64
|
+
- Fuzzy `/model` picker spanning every configured provider.
|
|
65
|
+
- Durable JSONL sessions with resume support.
|
|
66
|
+
- Context management with compaction, project instructions, and skill indexing.
|
|
67
|
+
- Live context-window usage in the status line (`tokens: 4.5k/256k`).
|
|
68
|
+
- Bold-red ANSI Shadow startup banner.
|
|
69
|
+
- Approval modes, workspace path boundaries, and hash-guarded writes.
|
|
70
|
+
- Non-gating performance benchmark suite for tools, startup, and TUI rendering.
|
|
71
|
+
|
|
72
|
+
[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,314 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Atom-lite
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/atom-lite)
|
|
4
|
+
[](https://github.com/beast-ofcourse/atom-lite/actions/workflows/ci.yml)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
[](https://www.typescriptlang.org)
|
|
7
|
+
[](./LICENSE)
|
|
8
|
+
|
|
9
|
+
**Atom-lite** is a local-first, model-agnostic coding agent with an intentionally small harness: one agent loop, four core built-in tools (`read`, `write`, `edit`, `bash`) plus network tools (`webfetch`, `websearch`), 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
|
+
> See [`docs/README.md`](./docs/README.md) for the documentation index 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 core tools plus two network 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
|
+
- **Six built-in tools** — four core tools (`read`, `write`, `edit`, `bash`) plus `webfetch` and `websearch`. 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
|
+
- **Command palette and themes** — `ctrl+p` fuzzy-searches commands, skills, providers, models, themes, and recent sessions. `/theme` switches between auto, dark, light, and no-colour modes.
|
|
55
|
+
- **Local-first** — runs fully against local providers with no cloud account, telemetry, or hosted database.
|
|
56
|
+
- **Safe path handling** — file tools resolve against the workspace and reject escapes; shell is an explicit, sandbox-aware boundary.
|
|
57
|
+
|
|
58
|
+
## Install
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
npm install -g atom-lite
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or run without installing:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
npx atom-lite "fix the failing test"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Requires **Node.js >= 22.19** (see `engines` in `package.json`).
|
|
71
|
+
|
|
72
|
+
## Quick start
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
atom-lite # interactive session in the current directory
|
|
76
|
+
atom-lite "task" # run one task, then exit
|
|
77
|
+
atom-lite --provider NAME # select a provider profile
|
|
78
|
+
atom-lite --continue # resume the most recent session
|
|
79
|
+
atom-lite --help
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Pipe a task via stdin:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
echo "summarize this repo" | atom-lite
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Default provider
|
|
89
|
+
|
|
90
|
+
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.
|
|
91
|
+
|
|
92
|
+
## Configuration
|
|
93
|
+
|
|
94
|
+
User config: `~/.config/atom-lite/config.json`
|
|
95
|
+
Project config: `.atom-lite/config.json` (non-secrets only)
|
|
96
|
+
|
|
97
|
+
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.
|
|
98
|
+
|
|
99
|
+
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.
|
|
100
|
+
|
|
101
|
+
Environment overrides:
|
|
102
|
+
|
|
103
|
+
| Variable | Effect |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| `ATOM_LITE_PROVIDER` | Default provider profile name |
|
|
106
|
+
| `ATOM_LITE_APPROVAL_MODE` | `ask` / `trusted` / `deny` |
|
|
107
|
+
|
|
108
|
+
Example `config.json`:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"defaultProvider": "kilo",
|
|
113
|
+
"providers": {
|
|
114
|
+
"kilo": {
|
|
115
|
+
"type": "openai-compatible",
|
|
116
|
+
"baseUrl": "https://api.kilo.ai/api/gateway",
|
|
117
|
+
"model": "kilo-auto/free",
|
|
118
|
+
"apiKeyEnv": null
|
|
119
|
+
},
|
|
120
|
+
"ollama": {
|
|
121
|
+
"type": "ollama",
|
|
122
|
+
"baseUrl": "http://127.0.0.1:11434",
|
|
123
|
+
"model": "qwen2.5-coder:7b"
|
|
124
|
+
},
|
|
125
|
+
"gemini": {
|
|
126
|
+
"type": "gemini",
|
|
127
|
+
"model": "gemini-2.0-flash",
|
|
128
|
+
"apiKeyEnv": "GEMINI_API_KEY"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"runtime": {
|
|
132
|
+
"approvalMode": "ask",
|
|
133
|
+
"bashConcurrency": "serial",
|
|
134
|
+
"maxIterations": 40,
|
|
135
|
+
"maxToolCalls": 100
|
|
136
|
+
},
|
|
137
|
+
"context": {
|
|
138
|
+
"maxInputTokens": null,
|
|
139
|
+
"reserveOutputTokens": 4096,
|
|
140
|
+
"compactAtPercent": 85
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
See [`docs/configuration.md`](./docs/configuration.md) for every field, default, and precedence rule.
|
|
146
|
+
|
|
147
|
+
## Usage
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
atom-lite [task] [--provider NAME] [--model MODEL] [--continue] [--session ID]
|
|
151
|
+
[--list-sessions] [--search-sessions QUERY] [--no-tools] [--json]
|
|
152
|
+
[--debug] [--theme NAME] [--no-color] [--version] [--help]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
| Flag | Description |
|
|
156
|
+
| --- | --- |
|
|
157
|
+
| `task` | One-shot task; agent runs it and exits |
|
|
158
|
+
| `--provider NAME` | Select a provider profile |
|
|
159
|
+
| `--model MODEL` | Override the model for this run |
|
|
160
|
+
| `--continue` | Resume the most recent session in this workspace |
|
|
161
|
+
| `--session ID` | Resume a specific session |
|
|
162
|
+
| `--list-sessions` | Print the session index and exit |
|
|
163
|
+
| `--search-sessions QUERY` | Print matching sessions with snippets and exit |
|
|
164
|
+
| `--no-tools` | Disable all tools (model-only chat) |
|
|
165
|
+
| `--json` | Non-interactive JSON output |
|
|
166
|
+
| `--debug` | Debug logging |
|
|
167
|
+
| `--theme NAME` | Use `auto`, `dark`, `light`, or `ansi` for this run |
|
|
168
|
+
| `--no-color` | Force the no-colour theme |
|
|
169
|
+
| `--version` | Print version |
|
|
170
|
+
| `--help` | Show help |
|
|
171
|
+
|
|
172
|
+
In the TUI, type `/help` to see every command grouped by category, or press
|
|
173
|
+
`ctrl+p` for the fuzzy command palette. `/theme` opens a live-preview picker and
|
|
174
|
+
persists your choice to user config; `NO_COLOR` and `--no-color` always win.
|
|
175
|
+
`/sessions` opens a searchable session picker scoped to the current workspace,
|
|
176
|
+
with a toggle for all workspaces, and `/search <query>` prints matching sessions
|
|
177
|
+
with content snippets. Mouse wheel scrolling and click-to-focus are enabled for
|
|
178
|
+
interactive terminals and can be disabled with `ui.mouse: false`.
|
|
179
|
+
|
|
180
|
+
## Tools
|
|
181
|
+
|
|
182
|
+
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):
|
|
183
|
+
|
|
184
|
+
| Tool | Purpose |
|
|
185
|
+
| --- | --- |
|
|
186
|
+
| `read` | Inspect files (with optional line ranges) |
|
|
187
|
+
| `write` | Create or replace files safely (hash-guarded) |
|
|
188
|
+
| `edit` | Precise find-and-replace edits (hash-guarded) |
|
|
189
|
+
| `bash` | Execute shell commands (global exclusive barrier by default) |
|
|
190
|
+
| `webfetch` | Fetch a URL and convert HTML to markdown |
|
|
191
|
+
| `websearch` | Search the web and return ranked results |
|
|
192
|
+
|
|
193
|
+
File discovery, search, tests, Git, builds, formatters, and package managers are available through `bash`, not through additional built-in tools.
|
|
194
|
+
|
|
195
|
+
## Providers
|
|
196
|
+
|
|
197
|
+
| Type | Adapter | Notes |
|
|
198
|
+
| --- | --- | --- |
|
|
199
|
+
| `openai-compatible` | `OpenAICompatibleAdapter` | LM Studio, llama.cpp/llama-server, Kilo AI Gateway, and other compatible endpoints |
|
|
200
|
+
| `ollama` | `OllamaAdapter` | Native Ollama chat API |
|
|
201
|
+
| `gemini` | `GeminiAdapter` | Official Gemini API |
|
|
202
|
+
|
|
203
|
+
Provider profiles are named combinations of endpoint, model, auth source, and options. Switching profiles mid-tool-exchange is disallowed.
|
|
204
|
+
|
|
205
|
+
### Interactive setup
|
|
206
|
+
|
|
207
|
+
- `/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`).
|
|
208
|
+
- `/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.
|
|
209
|
+
- `/model <provider>/<model>` and `/provider <name>` are the non-interactive forms.
|
|
210
|
+
|
|
211
|
+
The selected provider/model is persisted to the user config, so the next session starts where you left off.
|
|
212
|
+
|
|
213
|
+
## Safety & security
|
|
214
|
+
|
|
215
|
+
- **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.
|
|
216
|
+
- **Approval modes** — `ask` prompts before each shell command; `trusted` auto-approves; `deny` blocks. Session trust can be granted interactively (`t`).
|
|
217
|
+
- **Hash guards** — prevent stale overwrites when a file changed since it was read.
|
|
218
|
+
- **Sandboxing flags** — reported per command; see `src/security/`.
|
|
219
|
+
- **No secrets in config** — interactive provider setup stores API keys in `~/.config/atom-lite/credentials.json` with `0600` permissions; environment variables still take precedence.
|
|
220
|
+
- **Local-first** — no cloud account, telemetry, or remote control plane required (see [ADR 0004](./docs/adr/0004-local-first-no-cloud-dependency.md)).
|
|
221
|
+
|
|
222
|
+
## Commands
|
|
223
|
+
|
|
224
|
+
Type `/help` for the grouped list, or press `ctrl+p` for the fuzzy command
|
|
225
|
+
palette. Common commands:
|
|
226
|
+
|
|
227
|
+
| Command | Description |
|
|
228
|
+
| --- | --- |
|
|
229
|
+
| `/model [model]` | Show or switch the active model |
|
|
230
|
+
| `/provider [profile]` | Show or switch the active provider |
|
|
231
|
+
| `/effort [low\|medium\|high]` | Set reasoning effort |
|
|
232
|
+
| `/session [rename <title>]` | Show or rename the current session |
|
|
233
|
+
| `/sessions [all]` | Search and resume a session |
|
|
234
|
+
| `/search <query>` | Search sessions by title or content |
|
|
235
|
+
| `/export [path]` | Export the session transcript |
|
|
236
|
+
| `/mcp [reconnect [server]]` | Inspect or reconnect MCP servers |
|
|
237
|
+
| `/extensions` | List loaded extensions |
|
|
238
|
+
| `/compact` | Compact older context |
|
|
239
|
+
| `/clear` | Clear the transcript view |
|
|
240
|
+
| `/approval` | Change approval mode |
|
|
241
|
+
| `/doctor` | Run diagnostics |
|
|
242
|
+
| `/thinking` | Toggle thinking display |
|
|
243
|
+
| `/theme [auto\|dark\|light\|ansi]` | Switch theme |
|
|
244
|
+
| `/skills`, `/skill <name>` | List or load a skill |
|
|
245
|
+
| `/exit` | Exit the TUI |
|
|
246
|
+
|
|
247
|
+
## Sessions
|
|
248
|
+
|
|
249
|
+
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.
|
|
250
|
+
|
|
251
|
+
The session index derives a title from the first user message unless `/session rename <title>` overrides it, and records the provider, update time, and message count. `/sessions` resumes a session in place: retained messages are replayed into the transcript and a `session_resumed` event is appended. `/search <query>` matches titles, message content, and workspace paths, ranking title hits first. `--list-sessions` and `--search-sessions` print the same index as stable tab-separated rows for scripts.
|
|
252
|
+
|
|
253
|
+
## Context management
|
|
254
|
+
|
|
255
|
+
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`.
|
|
256
|
+
|
|
257
|
+
## Development
|
|
258
|
+
|
|
259
|
+
```sh
|
|
260
|
+
npm install
|
|
261
|
+
npm run dev # run via tsx (src/cli/main.ts)
|
|
262
|
+
npm start # build and run
|
|
263
|
+
npm run typecheck # tsc --noEmit
|
|
264
|
+
npm test # build + node --test
|
|
265
|
+
npm run build # tsc
|
|
266
|
+
npm run format # prettier --write .
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Tests live in `tests/` (agent, config, runtime, tools). The project is TypeScript (strict) on NodeNext ESM.
|
|
270
|
+
|
|
271
|
+
### Releasing
|
|
272
|
+
|
|
273
|
+
1. Update `version` in `package.json` and add a `CHANGELOG.md` entry.
|
|
274
|
+
2. Run `npm run typecheck && npm test && npm run bench`.
|
|
275
|
+
3. Commit, then tag and push: `git tag vX.Y.Z && git push origin master --tags`.
|
|
276
|
+
4. The `Release` workflow stages the package on npm with provenance and opens a draft GitHub release. It requires an `NPM_TOKEN` repository secret with publish access.
|
|
277
|
+
5. Approve the staged version on npm (Staged Packages tab, or `npm stage approve <stage-id>` with 2FA), then publish the draft release on GitHub.
|
|
278
|
+
|
|
279
|
+
npm requires a maintainer with 2FA to approve staged releases; CI cannot complete that step.
|
|
280
|
+
|
|
281
|
+
## Architecture
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
src/
|
|
285
|
+
agent/ # agent loop & types
|
|
286
|
+
cli/ # terminal UI, approvals, commands
|
|
287
|
+
config/ # schema, defaults, loader
|
|
288
|
+
context/ # builder, manager, compaction, budget, instructions
|
|
289
|
+
providers/ # adapters (openai-compatible, ollama, gemini, fake) + factory
|
|
290
|
+
runtime/ # scheduler, approvals
|
|
291
|
+
security/ # paths, process, redaction
|
|
292
|
+
sessions/ # store, events, recovery
|
|
293
|
+
tools/ # read, write, edit, bash, webfetch, websearch, registry
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Key design decisions are recorded as ADRs in [`docs/adr/`](./docs/adr/):
|
|
297
|
+
|
|
298
|
+
- [0001 — Four built-in tools only](./docs/adr/0001-four-built-in-tools-only.md)
|
|
299
|
+
- [0002 — Single agent loop, no sub-agents in v1](./docs/adr/0002-single-agent-loop.md)
|
|
300
|
+
- [0003 — `bash` is a global exclusive barrier](./docs/adr/0003-bash-as-global-exclusive-barrier.md)
|
|
301
|
+
- [0004 — Local-first, no cloud dependency](./docs/adr/0004-local-first-no-cloud-dependency.md)
|
|
302
|
+
- [0005 — OpenTUI for the terminal UI](./docs/adr/0005-opentui-for-terminal-ui.md) (superseded by 0007)
|
|
303
|
+
- [0006 — Expanded built-in toolset (webfetch, websearch)](./docs/adr/0006-expanded-toolset.md)
|
|
304
|
+
- [0007 — pi-tui replaces OpenTUI](./docs/adr/0007-pi-tui-replaces-opentui.md)
|
|
305
|
+
|
|
306
|
+
## Contributing
|
|
307
|
+
|
|
308
|
+
Read [`CONTRIBUTING.md`](./CONTRIBUTING.md) before opening a pull request. Issues and specs live as markdown under `.scratch/` (see [`docs/agents/issue-tracker.md`](./docs/agents/issue-tracker.md)). Please keep changes consistent with the "small core" principle: new tools require strong justification against ADR 0001.
|
|
309
|
+
|
|
310
|
+
Report vulnerabilities privately as described in [`SECURITY.md`](./SECURITY.md).
|
|
311
|
+
|
|
312
|
+
## License
|
|
313
|
+
|
|
314
|
+
MIT
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
/** Replace the toolset, e.g. after MCP discovery or a list_changed refresh. */
|
|
26
|
+
setTools(tools: AgentRuntimeOptions["tools"]): void;
|
|
27
|
+
getEffort(): string;
|
|
28
|
+
runAgentTurn(input: string, session: {
|
|
29
|
+
messages: Message[];
|
|
30
|
+
appendMessage(m: Message): void;
|
|
31
|
+
}, signal: AbortSignal): Promise<string>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
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
|
+
/** Replace the toolset, e.g. after MCP discovery or a list_changed refresh. */
|
|
80
|
+
setTools(tools) {
|
|
81
|
+
this.tools = tools;
|
|
82
|
+
this.toolMap = new Map(tools.map((t) => [t.definition.name, t]));
|
|
83
|
+
}
|
|
84
|
+
getEffort() {
|
|
85
|
+
return this.effort;
|
|
86
|
+
}
|
|
87
|
+
async runAgentTurn(input, session, signal) {
|
|
88
|
+
session.appendMessage({ role: "user", content: [{ type: "text", text: input }] });
|
|
89
|
+
let totalToolCalls = 0;
|
|
90
|
+
const start = Date.now();
|
|
91
|
+
for (let iteration = 0; iteration < this.limits.maxIterations; iteration++) {
|
|
92
|
+
if (signal.aborted) {
|
|
93
|
+
throw new Error("USER_CANCELLED");
|
|
94
|
+
}
|
|
95
|
+
if (Date.now() - start > this.limits.maxExecutionMs) {
|
|
96
|
+
return "TASK_BUDGET_REACHED";
|
|
97
|
+
}
|
|
98
|
+
const messages = await this.contextManager.build(this.workspace, session.messages);
|
|
99
|
+
if (this.contextManager.consumeCompaction()) {
|
|
100
|
+
// Peers treat usage as unknown after compaction until the next
|
|
101
|
+
// assistant response reports fresh numbers.
|
|
102
|
+
this.contextUsed = undefined;
|
|
103
|
+
this.emitContextUsage();
|
|
104
|
+
}
|
|
105
|
+
const request = {
|
|
106
|
+
model: this.model,
|
|
107
|
+
messages,
|
|
108
|
+
tools: this.tools.map((t) => t.definition),
|
|
109
|
+
signal,
|
|
110
|
+
options: { effort: this.effort },
|
|
111
|
+
};
|
|
112
|
+
let response;
|
|
113
|
+
let streamedText = "";
|
|
114
|
+
if (typeof this.provider.stream === "function") {
|
|
115
|
+
// Stream tokens as they arrive.
|
|
116
|
+
for await (const ev of this.provider.stream(request)) {
|
|
117
|
+
if (ev.type === "thinking") {
|
|
118
|
+
this.onEvent?.({ type: "thinking_delta", text: ev.text });
|
|
119
|
+
}
|
|
120
|
+
else if (ev.type === "text") {
|
|
121
|
+
streamedText += ev.text;
|
|
122
|
+
this.onEvent?.({ type: "assistant_delta", text: ev.text });
|
|
123
|
+
}
|
|
124
|
+
else if (ev.type === "done") {
|
|
125
|
+
response = ev.response;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (!response) {
|
|
129
|
+
// Fallback if stream ended without done
|
|
130
|
+
response = {
|
|
131
|
+
message: { role: "assistant", content: streamedText ? [{ type: "text", text: streamedText }] : undefined, toolCalls: undefined },
|
|
132
|
+
toolCalls: [],
|
|
133
|
+
finishReason: "stop",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
response = await this.provider.generate(request);
|
|
139
|
+
const t = response.message.content?.map((p) => (p.type === "text" ? p.text : "")).join("") ?? "";
|
|
140
|
+
if (t)
|
|
141
|
+
this.onEvent?.({ type: "assistant_text", text: t });
|
|
142
|
+
streamedText = t;
|
|
143
|
+
}
|
|
144
|
+
session.appendMessage(response.message);
|
|
145
|
+
if (response.usage) {
|
|
146
|
+
this.onEvent?.({ type: "usage", input: response.usage.input, output: response.usage.output });
|
|
147
|
+
const used = (response.usage.input ?? 0) + (response.usage.output ?? 0);
|
|
148
|
+
if (used > 0) {
|
|
149
|
+
// The latest assistant step's prompt + generated tokens is the
|
|
150
|
+
// current context occupancy (not a cumulative session total).
|
|
151
|
+
this.contextUsed = used;
|
|
152
|
+
this.emitContextUsage();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const text = streamedText || (response.message.content?.map((p) => (p.type === "text" ? p.text : "")).join("") ?? "");
|
|
156
|
+
const toolCalls = response.toolCalls ?? [];
|
|
157
|
+
if (toolCalls.length === 0) {
|
|
158
|
+
this.onEvent?.({ type: "final", text });
|
|
159
|
+
return text;
|
|
160
|
+
}
|
|
161
|
+
for (const c of toolCalls)
|
|
162
|
+
this.onEvent?.({ type: "tool_call", id: c.id, name: c.name, args: c.arguments });
|
|
163
|
+
totalToolCalls += toolCalls.length;
|
|
164
|
+
if (totalToolCalls > this.limits.maxToolCalls) {
|
|
165
|
+
return "TASK_BUDGET_REACHED";
|
|
166
|
+
}
|
|
167
|
+
const ctx = {
|
|
168
|
+
workspace: this.workspace,
|
|
169
|
+
signal,
|
|
170
|
+
maxBashTimeMs: this.limits.maxBashTimeMs,
|
|
171
|
+
maxToolOutputBytes: this.limits.maxToolOutputBytes,
|
|
172
|
+
approvals: this.approvals,
|
|
173
|
+
onToolOutput: (call, stream, text) => {
|
|
174
|
+
this.onEvent?.({
|
|
175
|
+
type: "tool_output",
|
|
176
|
+
toolCallId: call.id,
|
|
177
|
+
name: call.name,
|
|
178
|
+
stream,
|
|
179
|
+
text,
|
|
180
|
+
});
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
const results = await executeToolBatch(toolCalls, this.toolMap, ctx, this.limits.maxParallelToolCalls, signal, undefined, this.bashConcurrency);
|
|
184
|
+
for (const r of results) {
|
|
185
|
+
session.appendMessage({
|
|
186
|
+
role: "tool",
|
|
187
|
+
toolCallId: r.toolCallId,
|
|
188
|
+
name: r.name,
|
|
189
|
+
content: r.content,
|
|
190
|
+
});
|
|
191
|
+
this.onEvent?.({
|
|
192
|
+
type: "tool_result",
|
|
193
|
+
toolCallId: r.toolCallId,
|
|
194
|
+
name: r.name,
|
|
195
|
+
content: r.content,
|
|
196
|
+
isError: r.isError,
|
|
197
|
+
diff: r.diff,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return "TASK_BUDGET_REACHED";
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# 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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"}
|