codebase-cli 2.0.0-pre.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 (172) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +266 -0
  3. package/bin/codebase +2 -0
  4. package/dist/agent/agent.js +198 -0
  5. package/dist/agent/agent.js.map +1 -0
  6. package/dist/agent/config.js +117 -0
  7. package/dist/agent/config.js.map +1 -0
  8. package/dist/agent/events.js +153 -0
  9. package/dist/agent/events.js.map +1 -0
  10. package/dist/agent/router.js +35 -0
  11. package/dist/agent/router.js.map +1 -0
  12. package/dist/agent/system-prompt.js +21 -0
  13. package/dist/agent/system-prompt.js.map +1 -0
  14. package/dist/auth/cli.js +138 -0
  15. package/dist/auth/cli.js.map +1 -0
  16. package/dist/auth/credentials.js +105 -0
  17. package/dist/auth/credentials.js.map +1 -0
  18. package/dist/auth/flow.js +222 -0
  19. package/dist/auth/flow.js.map +1 -0
  20. package/dist/auth/pkce.js +46 -0
  21. package/dist/auth/pkce.js.map +1 -0
  22. package/dist/cli.js +69 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/clipboard/copy.js +106 -0
  25. package/dist/clipboard/copy.js.map +1 -0
  26. package/dist/commands/builtins.js +203 -0
  27. package/dist/commands/builtins.js.map +1 -0
  28. package/dist/commands/registry.js +65 -0
  29. package/dist/commands/registry.js.map +1 -0
  30. package/dist/commands/types.js +2 -0
  31. package/dist/commands/types.js.map +1 -0
  32. package/dist/compaction/engine.js +209 -0
  33. package/dist/compaction/engine.js.map +1 -0
  34. package/dist/compaction/tokens.js +79 -0
  35. package/dist/compaction/tokens.js.map +1 -0
  36. package/dist/compaction/types.js +2 -0
  37. package/dist/compaction/types.js.map +1 -0
  38. package/dist/diagnostics/checkers.js +211 -0
  39. package/dist/diagnostics/checkers.js.map +1 -0
  40. package/dist/diagnostics/engine.js +71 -0
  41. package/dist/diagnostics/engine.js.map +1 -0
  42. package/dist/diagnostics/types.js +2 -0
  43. package/dist/diagnostics/types.js.map +1 -0
  44. package/dist/dotenv/loader.js +115 -0
  45. package/dist/dotenv/loader.js.map +1 -0
  46. package/dist/glue/client.js +47 -0
  47. package/dist/glue/client.js.map +1 -0
  48. package/dist/glue/intent.js +78 -0
  49. package/dist/glue/intent.js.map +1 -0
  50. package/dist/glue/narration.js +55 -0
  51. package/dist/glue/narration.js.map +1 -0
  52. package/dist/headless/run.js +89 -0
  53. package/dist/headless/run.js.map +1 -0
  54. package/dist/hooks/manager.js +158 -0
  55. package/dist/hooks/manager.js.map +1 -0
  56. package/dist/hooks/runner.js +70 -0
  57. package/dist/hooks/runner.js.map +1 -0
  58. package/dist/hooks/types.js +2 -0
  59. package/dist/hooks/types.js.map +1 -0
  60. package/dist/memory/inject.js +12 -0
  61. package/dist/memory/inject.js.map +1 -0
  62. package/dist/memory/store.js +178 -0
  63. package/dist/memory/store.js.map +1 -0
  64. package/dist/memory/types.js +10 -0
  65. package/dist/memory/types.js.map +1 -0
  66. package/dist/permissions/store.js +172 -0
  67. package/dist/permissions/store.js.map +1 -0
  68. package/dist/plan/flow.js +214 -0
  69. package/dist/plan/flow.js.map +1 -0
  70. package/dist/plan/prompts.js +69 -0
  71. package/dist/plan/prompts.js.map +1 -0
  72. package/dist/plan/store.js +37 -0
  73. package/dist/plan/store.js.map +1 -0
  74. package/dist/plan/types.js +3 -0
  75. package/dist/plan/types.js.map +1 -0
  76. package/dist/sessions/store.js +105 -0
  77. package/dist/sessions/store.js.map +1 -0
  78. package/dist/skills/loader.js +41 -0
  79. package/dist/skills/loader.js.map +1 -0
  80. package/dist/skills/platform-loader.js +63 -0
  81. package/dist/skills/platform-loader.js.map +1 -0
  82. package/dist/skills/types.js +21 -0
  83. package/dist/skills/types.js.map +1 -0
  84. package/dist/tools/ask-user.js +61 -0
  85. package/dist/tools/ask-user.js.map +1 -0
  86. package/dist/tools/dispatch-agent.js +178 -0
  87. package/dist/tools/dispatch-agent.js.map +1 -0
  88. package/dist/tools/edit-file.js +80 -0
  89. package/dist/tools/edit-file.js.map +1 -0
  90. package/dist/tools/errors.js +89 -0
  91. package/dist/tools/errors.js.map +1 -0
  92. package/dist/tools/file-ops.js +136 -0
  93. package/dist/tools/file-ops.js.map +1 -0
  94. package/dist/tools/file-state-cache.js +92 -0
  95. package/dist/tools/file-state-cache.js.map +1 -0
  96. package/dist/tools/git/branch.js +84 -0
  97. package/dist/tools/git/branch.js.map +1 -0
  98. package/dist/tools/git/commit.js +83 -0
  99. package/dist/tools/git/commit.js.map +1 -0
  100. package/dist/tools/git/diff.js +72 -0
  101. package/dist/tools/git/diff.js.map +1 -0
  102. package/dist/tools/git/git-helpers.js +58 -0
  103. package/dist/tools/git/git-helpers.js.map +1 -0
  104. package/dist/tools/git/log.js +70 -0
  105. package/dist/tools/git/log.js.map +1 -0
  106. package/dist/tools/git/status.js +97 -0
  107. package/dist/tools/git/status.js.map +1 -0
  108. package/dist/tools/git/worktree.js +132 -0
  109. package/dist/tools/git/worktree.js.map +1 -0
  110. package/dist/tools/glob.js +128 -0
  111. package/dist/tools/glob.js.map +1 -0
  112. package/dist/tools/grep.js +199 -0
  113. package/dist/tools/grep.js.map +1 -0
  114. package/dist/tools/list-files.js +120 -0
  115. package/dist/tools/list-files.js.map +1 -0
  116. package/dist/tools/memory-tools.js +127 -0
  117. package/dist/tools/memory-tools.js.map +1 -0
  118. package/dist/tools/multi-edit.js +87 -0
  119. package/dist/tools/multi-edit.js.map +1 -0
  120. package/dist/tools/notebook-edit.js +147 -0
  121. package/dist/tools/notebook-edit.js.map +1 -0
  122. package/dist/tools/permission.js +168 -0
  123. package/dist/tools/permission.js.map +1 -0
  124. package/dist/tools/plan-mode.js +76 -0
  125. package/dist/tools/plan-mode.js.map +1 -0
  126. package/dist/tools/read-file.js +135 -0
  127. package/dist/tools/read-file.js.map +1 -0
  128. package/dist/tools/registry.js +52 -0
  129. package/dist/tools/registry.js.map +1 -0
  130. package/dist/tools/shell.js +216 -0
  131. package/dist/tools/shell.js.map +1 -0
  132. package/dist/tools/task-store.js +70 -0
  133. package/dist/tools/task-store.js.map +1 -0
  134. package/dist/tools/tasks.js +131 -0
  135. package/dist/tools/tasks.js.map +1 -0
  136. package/dist/tools/types.js +2 -0
  137. package/dist/tools/types.js.map +1 -0
  138. package/dist/tools/web-fetch.js +152 -0
  139. package/dist/tools/web-fetch.js.map +1 -0
  140. package/dist/tools/web-search.js +169 -0
  141. package/dist/tools/web-search.js.map +1 -0
  142. package/dist/tools/write-file.js +70 -0
  143. package/dist/tools/write-file.js.map +1 -0
  144. package/dist/types.js +9 -0
  145. package/dist/types.js.map +1 -0
  146. package/dist/ui/App.js +216 -0
  147. package/dist/ui/App.js.map +1 -0
  148. package/dist/ui/Input.js +90 -0
  149. package/dist/ui/Input.js.map +1 -0
  150. package/dist/ui/Message.js +89 -0
  151. package/dist/ui/Message.js.map +1 -0
  152. package/dist/ui/MessageList.js +35 -0
  153. package/dist/ui/MessageList.js.map +1 -0
  154. package/dist/ui/Permission.js +39 -0
  155. package/dist/ui/Permission.js.map +1 -0
  156. package/dist/ui/Status.js +34 -0
  157. package/dist/ui/Status.js.map +1 -0
  158. package/dist/ui/TaskPanel.js +43 -0
  159. package/dist/ui/TaskPanel.js.map +1 -0
  160. package/dist/ui/Throbber.js +20 -0
  161. package/dist/ui/Throbber.js.map +1 -0
  162. package/dist/ui/ToolPanel.js +83 -0
  163. package/dist/ui/ToolPanel.js.map +1 -0
  164. package/dist/ui/UserQuery.js +38 -0
  165. package/dist/ui/UserQuery.js.map +1 -0
  166. package/dist/ui/input-state.js +210 -0
  167. package/dist/ui/input-state.js.map +1 -0
  168. package/dist/ui/wrap.js +30 -0
  169. package/dist/ui/wrap.js.map +1 -0
  170. package/dist/user-queries/store.js +60 -0
  171. package/dist/user-queries/store.js.map +1 -0
  172. package/package.json +76 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Codebase Foundation
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 ADDED
@@ -0,0 +1,266 @@
1
+ # Codebase CLI
2
+
3
+ AI coding agent in your terminal. Reads your project, writes code, runs commands, searches the web. Works with any LLM provider — or sign in with codebase.foundation and we proxy inference for you.
4
+
5
+ > **v2 (TypeScript)** — codebase-cli has been rewritten on top of the
6
+ > [pi-mono](https://github.com/earendil-works/pi-mono) runtime. Existing
7
+ > v1 (Go) users: the installer below auto-detects the old binary and
8
+ > migrates your data. See [`docs/MIGRATION_v1_to_v2.md`](docs/MIGRATION_v1_to_v2.md).
9
+
10
+ ## Install
11
+
12
+ Requires **Node.js ≥ 20**. The one-liner installer prints a hint with Volta/fnm/nvm if Node is missing or too old.
13
+
14
+ **macOS / Linux (one-liner — recommended):**
15
+
16
+ ```sh
17
+ curl -fsSL https://codebase.design/install.sh | sh
18
+ ```
19
+
20
+ This detects an existing v1 binary, asks before removing it, then installs v2 via npm.
21
+
22
+ **Windows (PowerShell):**
23
+
24
+ ```powershell
25
+ irm https://codebase.design/install.ps1 | iex
26
+ ```
27
+
28
+ **With npm (any platform, requires Node.js ≥ 20):**
29
+
30
+ ```sh
31
+ npm install -g codebase-cli
32
+ ```
33
+
34
+ **With Homebrew:**
35
+
36
+ ```sh
37
+ brew install codebase-foundation/codebase/codebase
38
+ ```
39
+
40
+ **From source:**
41
+
42
+ ```sh
43
+ git clone https://github.com/codebase-foundation/codebase-cli.git
44
+ cd codebase-cli
45
+ npm install
46
+ npm run build
47
+ npm link # symlinks `codebase` into your npm prefix
48
+ ```
49
+
50
+ After install, run `codebase` from any project directory.
51
+
52
+ ## Quick Start
53
+
54
+ **Option 1: Login with Codebase (easiest)**
55
+
56
+ ```sh
57
+ codebase auth login
58
+ ```
59
+
60
+ Opens your browser, logs you into codebase.foundation, and you're ready. Uses our inference providers (Claude, MiniMax, Qwen, etc.) with your account credits. No API keys needed.
61
+
62
+ **Option 2: Bring your own API key**
63
+
64
+ ```sh
65
+ export ANTHROPIC_API_KEY=sk-ant-...
66
+ codebase
67
+ ```
68
+
69
+ Works with any provider:
70
+
71
+ ```sh
72
+ # OpenAI
73
+ export OPENAI_API_KEY=sk-...
74
+
75
+ # Groq
76
+ export OPENAI_BASE_URL=https://api.groq.com/openai/v1
77
+ export OPENAI_API_KEY=gsk-...
78
+ export OPENAI_MODEL=llama-3.3-70b-versatile
79
+
80
+ # Ollama (local, free)
81
+ export OPENAI_BASE_URL=http://localhost:11434/v1
82
+ export OPENAI_API_KEY=ollama
83
+ export OPENAI_MODEL=qwen2.5-coder:32b
84
+ ```
85
+
86
+ **Option 3: First-run setup wizard**
87
+
88
+ Just run `codebase` with no config. The setup wizard walks you through picking a provider, entering your key, and selecting a model. "Login with Codebase" is the first option.
89
+
90
+ ## What It Does
91
+
92
+ You describe what you want. The agent reads your code, makes changes, runs commands, and explains what it did.
93
+
94
+ ```
95
+ > add a /health endpoint that returns uptime and version
96
+
97
+ read_file server.go ✓
98
+ read_file go.mod ✓
99
+ edit_file server.go ✓
100
+ shell go build ./... ✓
101
+
102
+ Added GET /health endpoint at server.go:47 returning JSON with
103
+ uptime, version, and go runtime. Build passes.
104
+ ```
105
+
106
+ ## Tools (30)
107
+
108
+ | Category | Tools |
109
+ |----------|-------|
110
+ | **File read** | `read_file`, `list_files`, `glob`, `grep`, `search_files` |
111
+ | **File write** | `write_file`, `edit_file`, `multi_edit`, `notebook_edit` |
112
+ | **Shell** | `shell` (input-aware parallelism — read-only commands run concurrently) |
113
+ | **Git** | `git_status`, `git_diff`, `git_log`, `git_commit`, `git_branch`, `enter_worktree`, `exit_worktree` |
114
+ | **Web** | `web_search`, `web_fetch` |
115
+ | **Agent** | `dispatch_agent` (explore, plan, or general-purpose subagents with optional worktree isolation) |
116
+ | **Tasks** | `create_task`, `update_task`, `list_tasks`, `get_task` |
117
+ | **Planning** | `enter_plan_mode`, `exit_plan_mode` |
118
+ | **Memory** | `save_memory`, `read_memory` (persist context across sessions) |
119
+ | **Other** | `config`, `ask_user` |
120
+
121
+ Plus any tools from connected MCP servers.
122
+
123
+ ## Commands (22)
124
+
125
+ | Command | What it does |
126
+ |---------|-------------|
127
+ | `/help` | List all commands |
128
+ | `/status` | Model, tokens, turns, cost |
129
+ | `/cost` | Token usage and estimated cost |
130
+ | `/context` | Visual context window usage bar |
131
+ | `/model [name]` | Show or switch model |
132
+ | `/commit` | Generate commit from current diff |
133
+ | `/review` | Code review of uncommitted changes |
134
+ | `/plan` | Enter planning mode |
135
+ | `/diff` | Open diff in VS Code/Cursor |
136
+ | `/compact` | Manually compact conversation |
137
+ | `/clear` | Clear display |
138
+ | `/memory` | View saved project memories |
139
+ | `/undo [file]` | Revert file from session history or git |
140
+ | `/export [file]` | Export conversation to markdown |
141
+ | `/tasks` | Show task checklist |
142
+ | `/theme` | Switch color theme |
143
+ | `/trust` | Set permission level |
144
+ | `/diagnostics` | Toggle language checkers |
145
+ | `/copy` | Copy last response to clipboard |
146
+ | `/session` | Full session info |
147
+ | `/setup` | Re-run setup wizard |
148
+ | `/quit` | Exit (or ctrl+c twice) |
149
+
150
+ ## Features
151
+
152
+ - **30 tools** with schema validation and input-dependent parallel execution
153
+ - **Streaming tool execution** — tools start running before the model finishes responding
154
+ - **3 agent types** — explore (read-only), plan (architecture), general-purpose (full access)
155
+ - **Worktree isolation** — subagents can work in isolated git branches
156
+ - **Cross-session memory** — remembers your preferences and project context
157
+ - **Error recovery** — auto-retries on context overflow, output limits, rate limits
158
+ - **Structured compaction** — 9-section summaries when context gets long
159
+ - **Hooks system** — automate lint/test/format after edits
160
+ - **7 language checkers** — Go, TypeScript, ESLint, Python (pyright/mypy), Rust
161
+ - **MCP support** — connect external tool servers for extensibility
162
+ - **IDE detection** — discovers VS Code/Cursor/JetBrains via lockfiles
163
+ - **File history** — undo any edit within the session, even without git
164
+ - **Glue models** — route cheap tasks to a fast model, save money
165
+ - **Permission explainer** — risk-rated permission prompts (LOW/MEDIUM/HIGH)
166
+ - **Multi-provider** — OpenAI, Anthropic, MiniMax, Groq, Ollama, any compatible endpoint
167
+ - **OAuth-aware platform** — sign-in unlocks proxied inference and account-curated skills/templates/prompts
168
+
169
+ ## Authentication
170
+
171
+ ```sh
172
+ codebase auth login # browser OAuth — log in with Google, GitHub, or wallet
173
+ codebase auth <cbk_xxx> # save an API key from the dashboard (SSH / headless)
174
+ codebase auth status # show current sign-in
175
+ codebase auth refresh # force-refresh the access token
176
+ codebase auth logout # revoke session
177
+ ```
178
+
179
+ Credentials are stored at `~/.codebase/credentials.json` (mode 0600).
180
+
181
+ When logged in, the CLI routes through `codebase.foundation` — you get access to all providers (Claude, MiniMax, Qwen, etc.) using your account credits. No API keys to manage. Skill, template, and prompt definitions you author in the web app become available automatically (Phase 7+).
182
+
183
+ ## MCP (External Tool Servers)
184
+
185
+ Connect to any MCP-compatible server. Add to `~/.codebase/config.json`:
186
+
187
+ ```json
188
+ {
189
+ "mcp_servers": {
190
+ "github": {
191
+ "command": "mcp-server-github",
192
+ "args": ["--token", "$GITHUB_TOKEN"],
193
+ "transport": "stdio"
194
+ }
195
+ }
196
+ }
197
+ ```
198
+
199
+ MCP tools appear alongside built-in tools automatically.
200
+
201
+ ## Hooks
202
+
203
+ Automate actions on events. Add to `~/.codebase/hooks.json`:
204
+
205
+ ```json
206
+ [
207
+ {
208
+ "event": "PostEdit",
209
+ "matcher": "write_file|edit_file",
210
+ "command": "go vet ./...",
211
+ "timeout": 15
212
+ }
213
+ ]
214
+ ```
215
+
216
+ Events: `PreToolUse`, `PostToolUse`, `PostEdit`, `UserPromptSubmit`, `SessionStart`, `Stop`.
217
+
218
+ ## Project Instructions
219
+
220
+ The CLI reads these files from your project root for context:
221
+
222
+ - `CLAUDE.md` — project instructions (Claude Code convention)
223
+ - `AGENTS.md` — agent instructions (OpenAI Codex convention)
224
+ - `CODEX.md` — project instructions (Codex convention)
225
+ - `.cursorrules` — project instructions (Cursor convention)
226
+
227
+ ## Flags
228
+
229
+ ```
230
+ codebase # run in current directory
231
+ codebase --dir /path/to/proj # run in specific directory
232
+ codebase --model claude-sonnet-4-5 # override model
233
+ codebase --resume # resume previous session
234
+ codebase --version # print version
235
+ codebase auth login # authenticate with codebase.foundation
236
+ codebase auth logout # revoke authentication
237
+ codebase --headless "fix the build" # one-shot, no TUI
238
+ ```
239
+
240
+ ## Environment Variables
241
+
242
+ ```sh
243
+ # LLM Provider (pick one)
244
+ OPENAI_API_KEY=... # OpenAI or compatible
245
+ ANTHROPIC_API_KEY=... # Anthropic (auto-detected)
246
+ OPENAI_BASE_URL=... # Custom endpoint
247
+ OPENAI_MODEL=... # Override model
248
+
249
+ # Glue (optional — cheap model for routing/narration)
250
+ GLUE_API_KEY=...
251
+ GLUE_BASE_URL=...
252
+ GLUE_FAST_MODEL=...
253
+ GLUE_SMART_MODEL=...
254
+
255
+ # Web Search (optional — DuckDuckGo works without keys)
256
+ TAVILY_API_KEY=...
257
+ BRAVE_API_KEY=...
258
+
259
+ # Behavior
260
+ CODEBASE_NOBOOT=1 # skip boot animation
261
+ CODEBASE_NOSOUND=1 # skip boot audio
262
+ ```
263
+
264
+ ## License
265
+
266
+ MIT
package/bin/codebase ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import("../dist/cli.js");
@@ -0,0 +1,198 @@
1
+ import { homedir } from "node:os";
2
+ import { isAbsolute, join, resolve } from "node:path";
3
+ import { Agent } from "@earendil-works/pi-agent-core";
4
+ import { CompactionEngine } from "../compaction/engine.js";
5
+ import { DiagnosticsEngine, formatDiagnostics } from "../diagnostics/engine.js";
6
+ import { GlueClient, resolveGlueModels } from "../glue/client.js";
7
+ import { HookManager } from "../hooks/manager.js";
8
+ import { buildMemoryAddendum } from "../memory/inject.js";
9
+ import { MemoryStore } from "../memory/store.js";
10
+ import { PermissionStore } from "../permissions/store.js";
11
+ import { PlanModeStore } from "../plan/store.js";
12
+ import { SessionStore } from "../sessions/store.js";
13
+ import { FileStateCache } from "../tools/file-state-cache.js";
14
+ import { buildTools } from "../tools/registry.js";
15
+ import { TaskStore } from "../tools/task-store.js";
16
+ import { UserQueryStore } from "../user-queries/store.js";
17
+ import { resolveConfig } from "./config.js";
18
+ import { buildSystemPrompt } from "./system-prompt.js";
19
+ const WRITE_TOOL_NAMES = new Set(["write_file", "edit_file", "multi_edit", "notebook_edit"]);
20
+ /**
21
+ * Tools blocked while plan mode is active. Anything that mutates working-tree
22
+ * state, runs commands, or talks to git's index belongs here. Read tools
23
+ * (read_file, list_files, glob, grep, dispatch_agent, web_*, git read trio)
24
+ * stay available so the agent can investigate and write the plan.
25
+ */
26
+ const PLAN_MODE_BLOCKED = new Set([
27
+ "write_file",
28
+ "edit_file",
29
+ "multi_edit",
30
+ "notebook_edit",
31
+ "shell",
32
+ "git_commit",
33
+ "git_branch",
34
+ "enter_worktree",
35
+ "exit_worktree",
36
+ ]);
37
+ export function createAgent(opts = {}) {
38
+ const { model, apiKey, source } = resolveConfig();
39
+ const cwd = opts.cwd ?? process.cwd();
40
+ const systemPrompt = opts.systemPrompt ?? buildSystemPrompt(cwd);
41
+ const permissions = new PermissionStore();
42
+ const userQueries = new UserQueryStore();
43
+ const planMode = new PlanModeStore();
44
+ const memory = new MemoryStore({ cwd });
45
+ const hooks = new HookManager();
46
+ hooks.loadFrom(join(homedir(), ".codebase", "hooks.json"), join(cwd, ".codebase", "hooks.json"));
47
+ const diagnostics = new DiagnosticsEngine({ cwd });
48
+ const glueModels = resolveGlueModels({ parentModel: model, parentApiKey: apiKey });
49
+ const glue = new GlueClient({
50
+ fastModel: glueModels.fast,
51
+ smartModel: glueModels.smart,
52
+ apiKey: glueModels.apiKey,
53
+ });
54
+ const compaction = new CompactionEngine({ glue, modelId: model.id });
55
+ const sessions = new SessionStore({ cwd });
56
+ const resumed = opts.resume ? sessions.load(model.id) : null;
57
+ const toolContext = {
58
+ cwd,
59
+ fileStateCache: new FileStateCache(),
60
+ tasks: new TaskStore(),
61
+ userQueries,
62
+ planMode,
63
+ memory,
64
+ spawnSubagent: ({ systemPrompt: subPrompt, tools: subTools }) => new Agent({
65
+ initialState: { model, systemPrompt: subPrompt, tools: subTools },
66
+ getApiKey: () => apiKey,
67
+ }),
68
+ };
69
+ // MEMORY.md gets concatenated onto the system prompt at agent creation.
70
+ // Reload-after-save is a Phase 11 polish item.
71
+ const fullSystemPrompt = systemPrompt + buildMemoryAddendum(memory);
72
+ const agent = new Agent({
73
+ initialState: {
74
+ model,
75
+ systemPrompt: fullSystemPrompt,
76
+ tools: buildTools(toolContext),
77
+ messages: resumed?.messages ?? [],
78
+ },
79
+ getApiKey: () => apiKey,
80
+ transformContext: async (messages, signal) => {
81
+ if (!compaction.needsCompaction(messages))
82
+ return messages;
83
+ const result = await compaction.compact(messages, signal);
84
+ return result.messages;
85
+ },
86
+ beforeToolCall: async (ctx, signal) => {
87
+ // 1. Plan mode gate: block destructive tools entirely while planning.
88
+ if (planMode.isActive() && PLAN_MODE_BLOCKED.has(ctx.toolCall.name)) {
89
+ return {
90
+ block: true,
91
+ reason: `${ctx.toolCall.name} is blocked while plan mode is active. ` +
92
+ "Use exit_plan_mode after presenting your plan to regain write access.",
93
+ };
94
+ }
95
+ // 2. Built-in permission gate (fast, sync for read-only tools).
96
+ const decision = await permissions.evaluate(ctx.toolCall.name, ctx.args);
97
+ if (decision === "block") {
98
+ return { block: true, reason: "Permission denied by user." };
99
+ }
100
+ // 3. User-defined hooks (typically audit/lint/validation steps).
101
+ const filePath = ctx.args?.path;
102
+ const outcome = await hooks.dispatch("PreToolUse", {
103
+ event: "PreToolUse",
104
+ toolName: ctx.toolCall.name,
105
+ toolArgs: ctx.args,
106
+ filePath,
107
+ workingDir: cwd,
108
+ }, signal);
109
+ if (outcome.blocked) {
110
+ return { block: true, reason: outcome.reason ?? "Blocked by hook." };
111
+ }
112
+ return undefined;
113
+ },
114
+ afterToolCall: async (ctx, signal) => {
115
+ const filePath = ctx.args?.path;
116
+ await hooks.dispatch("PostToolUse", {
117
+ event: "PostToolUse",
118
+ toolName: ctx.toolCall.name,
119
+ toolArgs: ctx.args,
120
+ filePath,
121
+ workingDir: cwd,
122
+ }, signal);
123
+ // After a write/edit tool, run language checkers on the affected file
124
+ // and steer the result into the next turn. Fire-and-forget so the
125
+ // tool result return isn't blocked by a 15s checker run.
126
+ if (filePath && WRITE_TOOL_NAMES.has(ctx.toolCall.name)) {
127
+ const absPath = isAbsolute(filePath) ? filePath : resolve(cwd, filePath);
128
+ diagnostics
129
+ .forFiles([absPath], signal)
130
+ .then((diags) => {
131
+ if (diags.length === 0)
132
+ return;
133
+ const body = formatDiagnostics(diags);
134
+ agentRef?.steer({
135
+ role: "user",
136
+ content: `<system-reminder>\n${body}\n</system-reminder>`,
137
+ timestamp: Date.now(),
138
+ });
139
+ })
140
+ .catch(() => {
141
+ // Diagnostics failures are non-fatal — surface nothing.
142
+ });
143
+ }
144
+ return undefined;
145
+ },
146
+ });
147
+ // agentRef lets the afterToolCall closure call agent.steer() once the
148
+ // Agent is constructed. JS hoisting makes the assignment safe because
149
+ // afterToolCall fires inside the event loop, well after this assignment.
150
+ const agentRef = agent;
151
+ const subscribe = (listener) => agent.subscribe((event) => {
152
+ listener(event);
153
+ });
154
+ // Persist after every agent_end so a crash mid-session doesn't lose work.
155
+ agent.subscribe((event) => {
156
+ if (event.type !== "agent_end")
157
+ return;
158
+ try {
159
+ const messages = event.messages.length > 0 ? event.messages : (resumed?.messages ?? []);
160
+ if (messages.length === 0)
161
+ return;
162
+ sessions.save({
163
+ modelId: model.id,
164
+ title: resumed?.title ?? null,
165
+ messages,
166
+ usage: resumed?.usage ?? {
167
+ input: 0,
168
+ output: 0,
169
+ cacheRead: 0,
170
+ cacheWrite: 0,
171
+ totalTokens: 0,
172
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
173
+ },
174
+ });
175
+ }
176
+ catch {
177
+ // Persistence is best-effort — don't crash the agent over a write failure.
178
+ }
179
+ });
180
+ void agentRef;
181
+ return {
182
+ agent,
183
+ model,
184
+ source,
185
+ toolContext,
186
+ permissions,
187
+ userQueries,
188
+ planMode,
189
+ memory,
190
+ glue,
191
+ compaction,
192
+ sessions,
193
+ hooks,
194
+ diagnostics,
195
+ subscribe,
196
+ };
197
+ }
198
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import { getEnvApiKey, getModel } from "@earendil-works/pi-ai";
2
+ import { CredentialsStore } from "../auth/credentials.js";
3
+ /**
4
+ * Provider+model selection, in priority order:
5
+ * 1. Saved OAuth/API credentials (~/.codebase/credentials.json) — if
6
+ * present and not expired, route the chosen model through the
7
+ * codebase.foundation inference proxy so the backend can deduct
8
+ * credits. The model metadata stays the same; only baseUrl + apiKey
9
+ * change.
10
+ * 2. CODEBASE_PROVIDER + CODEBASE_MODEL env (explicit override)
11
+ * 3. First provider in {@link AUTO_DETECT_ORDER} with a usable env key
12
+ * 4. Throw — caller should surface this as an onboarding hint
13
+ *
14
+ * pi-ai's `getEnvApiKey` already handles every quirky case: OAuth-only
15
+ * providers, Vertex ADC, AWS multi-source. We just trust it.
16
+ */
17
+ const DEFAULT_PROXY_BASE = "https://codebase.foundation/api/cli";
18
+ const AUTO_DETECT_ORDER = [
19
+ "anthropic",
20
+ "openai",
21
+ "groq",
22
+ "google",
23
+ "mistral",
24
+ "deepseek",
25
+ "cerebras",
26
+ "xai",
27
+ "openrouter",
28
+ ];
29
+ const DEFAULT_MODELS = {
30
+ anthropic: "claude-sonnet-4-6",
31
+ openai: "gpt-5.1",
32
+ groq: "llama-3.3-70b-versatile",
33
+ google: "gemini-2.5-pro",
34
+ mistral: "mistral-large-latest",
35
+ deepseek: "deepseek-chat",
36
+ cerebras: "llama-3.3-70b",
37
+ xai: "grok-4",
38
+ openrouter: "anthropic/claude-sonnet-4-6",
39
+ };
40
+ export class ConfigError extends Error {
41
+ }
42
+ export function resolveConfig(envOrOpts = process.env) {
43
+ const opts = isProcessEnv(envOrOpts) ? { env: envOrOpts } : envOrOpts;
44
+ const env = opts.env ?? process.env;
45
+ const credentials = opts.credentials ?? new CredentialsStore();
46
+ // 1. OAuth/API credentials → proxy mode (unless explicitly disabled).
47
+ const useProxy = env.CODEBASE_DISABLE_PROXY !== "1";
48
+ if (useProxy) {
49
+ const creds = credentials.load();
50
+ if (creds && !credentials.isExpired(creds)) {
51
+ const proxied = buildProxiedConfig(env, creds.accessToken);
52
+ if (proxied)
53
+ return proxied;
54
+ }
55
+ }
56
+ const explicitProvider = env.CODEBASE_PROVIDER;
57
+ const explicitModel = env.CODEBASE_MODEL;
58
+ if (explicitProvider && explicitModel) {
59
+ const model = getModel(explicitProvider, explicitModel);
60
+ if (!model) {
61
+ throw new ConfigError(`CODEBASE_PROVIDER=${explicitProvider} CODEBASE_MODEL=${explicitModel} not in pi-ai's model registry. ` +
62
+ `Check the spelling, or unset both to auto-detect.`);
63
+ }
64
+ const apiKey = getEnvApiKey(explicitProvider);
65
+ if (!apiKey) {
66
+ throw new ConfigError(`CODEBASE_PROVIDER=${explicitProvider} has no API key in env. Set the appropriate *_API_KEY var.`);
67
+ }
68
+ return { model, apiKey, source: "explicit" };
69
+ }
70
+ for (const provider of AUTO_DETECT_ORDER) {
71
+ const apiKey = getEnvApiKey(provider);
72
+ if (!apiKey)
73
+ continue;
74
+ const modelId = DEFAULT_MODELS[provider];
75
+ if (!modelId)
76
+ continue;
77
+ const model = getModel(provider, modelId);
78
+ if (!model)
79
+ continue;
80
+ return { model, apiKey, source: "auto" };
81
+ }
82
+ throw new ConfigError("No usable LLM provider found. Sign in with `codebase auth login`, paste an API key with " +
83
+ "`codebase auth <key>`, or set one of: ANTHROPIC_API_KEY, OPENAI_API_KEY, GROQ_API_KEY, " +
84
+ "GOOGLE_API_KEY, MISTRAL_API_KEY, DEEPSEEK_API_KEY, CEREBRAS_API_KEY, XAI_API_KEY, OPENROUTER_API_KEY. " +
85
+ "Or set CODEBASE_PROVIDER + CODEBASE_MODEL explicitly.");
86
+ }
87
+ /**
88
+ * Build a model whose baseUrl points at the codebase.foundation
89
+ * inference proxy. The proxy MUST mimic the chosen provider's wire
90
+ * protocol (Anthropic Messages, OpenAI Responses, etc.) — what we send
91
+ * here is identical to a direct call, the bearer token is the only
92
+ * thing that changes.
93
+ */
94
+ function buildProxiedConfig(env, accessToken) {
95
+ const explicitProvider = env.CODEBASE_PROVIDER;
96
+ const explicitModel = env.CODEBASE_MODEL;
97
+ const provider = explicitProvider ?? "anthropic";
98
+ const modelId = explicitModel ?? DEFAULT_MODELS[provider];
99
+ if (!modelId)
100
+ return null;
101
+ const baseModel = getModel(provider, modelId);
102
+ if (!baseModel)
103
+ return null;
104
+ const proxyBase = (env.CODEBASE_PROXY_BASE_URL ?? DEFAULT_PROXY_BASE).replace(/\/+$/, "");
105
+ const proxiedModel = { ...baseModel, baseUrl: proxyBase };
106
+ return { model: proxiedModel, apiKey: accessToken, source: "proxy" };
107
+ }
108
+ function isProcessEnv(value) {
109
+ if (!value)
110
+ return true;
111
+ // ResolveConfigOptions has at most env/credentials properties; ProcessEnv has many.
112
+ const keys = Object.keys(value);
113
+ if (keys.length === 0)
114
+ return true;
115
+ return !keys.every((k) => k === "env" || k === "credentials");
116
+ }
117
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/agent/config.ts"],"names":[],"mappings":"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"}