chivgent 0.6.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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +359 -0
  3. package/README.zh-CN.md +345 -0
  4. package/dist/agent.d.ts +58 -0
  5. package/dist/agent.d.ts.map +1 -0
  6. package/dist/agent.js +281 -0
  7. package/dist/agent.js.map +1 -0
  8. package/dist/cli-options.d.ts +33 -0
  9. package/dist/cli-options.d.ts.map +1 -0
  10. package/dist/cli-options.js +151 -0
  11. package/dist/cli-options.js.map +1 -0
  12. package/dist/cli.d.ts +3 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +233 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/events.d.ts +79 -0
  17. package/dist/events.d.ts.map +1 -0
  18. package/dist/events.js +12 -0
  19. package/dist/events.js.map +1 -0
  20. package/dist/llm.d.ts +38 -0
  21. package/dist/llm.d.ts.map +1 -0
  22. package/dist/llm.js +17 -0
  23. package/dist/llm.js.map +1 -0
  24. package/dist/messages.d.ts +23 -0
  25. package/dist/messages.d.ts.map +1 -0
  26. package/dist/messages.js +2 -0
  27. package/dist/messages.js.map +1 -0
  28. package/dist/providers/deepseek.d.ts +12 -0
  29. package/dist/providers/deepseek.d.ts.map +1 -0
  30. package/dist/providers/deepseek.js +15 -0
  31. package/dist/providers/deepseek.js.map +1 -0
  32. package/dist/providers/openai-compatible-chat.d.ts +25 -0
  33. package/dist/providers/openai-compatible-chat.d.ts.map +1 -0
  34. package/dist/providers/openai-compatible-chat.js +293 -0
  35. package/dist/providers/openai-compatible-chat.js.map +1 -0
  36. package/dist/providers/openai.d.ts +16 -0
  37. package/dist/providers/openai.d.ts.map +1 -0
  38. package/dist/providers/openai.js +183 -0
  39. package/dist/providers/openai.js.map +1 -0
  40. package/dist/render.d.ts +26 -0
  41. package/dist/render.d.ts.map +1 -0
  42. package/dist/render.js +95 -0
  43. package/dist/render.js.map +1 -0
  44. package/dist/repl.d.ts +29 -0
  45. package/dist/repl.d.ts.map +1 -0
  46. package/dist/repl.js +119 -0
  47. package/dist/repl.js.map +1 -0
  48. package/dist/retry.d.ts +42 -0
  49. package/dist/retry.d.ts.map +1 -0
  50. package/dist/retry.js +186 -0
  51. package/dist/retry.js.map +1 -0
  52. package/dist/session-store.d.ts +66 -0
  53. package/dist/session-store.d.ts.map +1 -0
  54. package/dist/session-store.js +183 -0
  55. package/dist/session-store.js.map +1 -0
  56. package/dist/session.d.ts +49 -0
  57. package/dist/session.d.ts.map +1 -0
  58. package/dist/session.js +115 -0
  59. package/dist/session.js.map +1 -0
  60. package/dist/tools/list-files.d.ts +24 -0
  61. package/dist/tools/list-files.d.ts.map +1 -0
  62. package/dist/tools/list-files.js +80 -0
  63. package/dist/tools/list-files.js.map +1 -0
  64. package/dist/tools/output.d.ts +10 -0
  65. package/dist/tools/output.d.ts.map +1 -0
  66. package/dist/tools/output.js +44 -0
  67. package/dist/tools/output.js.map +1 -0
  68. package/dist/tools/read-file.d.ts +29 -0
  69. package/dist/tools/read-file.d.ts.map +1 -0
  70. package/dist/tools/read-file.js +150 -0
  71. package/dist/tools/read-file.js.map +1 -0
  72. package/dist/tools/search-text.d.ts +28 -0
  73. package/dist/tools/search-text.d.ts.map +1 -0
  74. package/dist/tools/search-text.js +94 -0
  75. package/dist/tools/search-text.js.map +1 -0
  76. package/dist/tools/tool.d.ts +22 -0
  77. package/dist/tools/tool.d.ts.map +1 -0
  78. package/dist/tools/tool.js +2 -0
  79. package/dist/tools/tool.js.map +1 -0
  80. package/dist/workspace.d.ts +72 -0
  81. package/dist/workspace.d.ts.map +1 -0
  82. package/dist/workspace.js +504 -0
  83. package/dist/workspace.js.map +1 -0
  84. package/package.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chiv
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,359 @@
1
+ # chivgent
2
+
3
+ [English](README.md) | [简体中文](README.zh-CN.md)
4
+
5
+ > A small, readable coding-agent CLI for learning how an agent harness actually
6
+ > works.
7
+
8
+ ![Node.js](https://img.shields.io/badge/Node.js-%3E%3D20-339933?logo=nodedotjs&logoColor=white)
9
+ ![TypeScript](https://img.shields.io/badge/TypeScript-ESM-3178C6?logo=typescript&logoColor=white)
10
+ [![CI](https://github.com/chivopic/chivgent/actions/workflows/ci.yml/badge.svg)](https://github.com/chivopic/chivgent/actions/workflows/ci.yml)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
12
+ ![Status](https://img.shields.io/badge/status-MVP-orange)
13
+
14
+ `chivgent` connects a Provider-independent agent loop to LLM APIs, tools, and a
15
+ workspace boundary. The current MVP can discover files, search source text, and
16
+ read bounded file ranges before answering with OpenAI, DeepSeek, or any
17
+ compatible Chat Completions endpoint.
18
+
19
+ The project is intentionally compact: it is designed to make the mechanics of
20
+ tool calling, conversation state, Provider adapters, and loop termination easy
21
+ to study before adding production-harness complexity.
22
+
23
+ ## Features
24
+
25
+ - A real multi-turn agent loop: model -> tool call -> tool result -> model.
26
+ - Provider-independent runtime messages and tool contracts.
27
+ - OpenAI support through the Responses API.
28
+ - DeepSeek support through a reusable OpenAI-compatible Chat Completions client.
29
+ - Custom OpenAI-compatible endpoints through environment-only configuration.
30
+ - An interactive session with slash commands, or a single-shot question.
31
+ - Sessions that persist as JSON lines and can be resumed in a later process.
32
+ - A `--json` event stream for scripting and other front ends.
33
+ - Streamed answers rendered from a typed runtime event stream.
34
+ - Interruptible runs: Ctrl+C ends the current run without losing the transcript.
35
+ - Per-attempt Provider timeouts and bounded exponential-backoff retries.
36
+ - Deterministic project discovery through `list_files` and literal `search_text`.
37
+ - Ranged `read_file` output with continuation hints and bounded tool results.
38
+ - Safe, read-only workspace access with traversal and symlink-escape protection.
39
+ - Root `.gitignore`, generated-directory, and sensitive-path filtering.
40
+ - Tool argument validation, explicit tool errors, and an eight-turn safety limit.
41
+ - A packaged Node.js CLI with no framework dependency.
42
+ - Unit tests that do not spend API credits.
43
+
44
+ ## Quick start
45
+
46
+ ### Requirements
47
+
48
+ - Node.js 20 or newer
49
+ - npm
50
+ - An API key for OpenAI, DeepSeek, or a compatible Provider
51
+
52
+ ### Install from npm
53
+
54
+ ```bash
55
+ npm install -g chivgent
56
+ chivgent --version
57
+ ```
58
+
59
+ To install the current source checkout instead:
60
+
61
+ ```bash
62
+ git clone https://github.com/chivopic/chivgent.git
63
+ cd chivgent
64
+ npm install
65
+ npm run build
66
+ npm install -g .
67
+ ```
68
+
69
+ ### Ask about a project
70
+
71
+ Run `chivgent` from the project you want it to inspect.
72
+
73
+ With OpenAI:
74
+
75
+ ```bash
76
+ export OPENAI_API_KEY="your-api-key"
77
+ chivgent "What does src/agent.ts do?"
78
+ ```
79
+
80
+ With DeepSeek:
81
+
82
+ ```bash
83
+ export DEEPSEEK_API_KEY="your-api-key"
84
+ chivgent --provider deepseek "Explain the architecture in src/"
85
+ ```
86
+
87
+ With any OpenAI-compatible Chat Completions endpoint:
88
+
89
+ ```bash
90
+ export OPENAI_API_KEY="your-provider-api-key"
91
+ export OPENAI_BASE_URL="https://api.vendor.example/v1"
92
+ export OPENAI_MODEL="vendor-model"
93
+
94
+ chivgent --provider openai-compatible "Explain the architecture in src/"
95
+ ```
96
+
97
+ Start an interactive session by running `chivgent` with no question:
98
+
99
+ ```bash
100
+ chivgent
101
+ › What does src/agent.ts do?
102
+ › Where is that loop tested?
103
+ › /exit
104
+ ```
105
+
106
+ The conversation is kept across prompts, so follow-up questions do not repeat
107
+ the earlier context. Resume it later with `chivgent --continue` (or
108
+ `chivgent --resume <id>`; `chivgent --sessions` lists what is recorded).
109
+
110
+ Answers stream to stdout as the model produces them, so stdout stays pipeable.
111
+ Tool activity, retries, and run status go to stderr; Provider failures produce a
112
+ non-zero exit code. Use `--no-stream` for one final write, and `--quiet` to hide
113
+ tool activity.
114
+
115
+ ## CLI reference
116
+
117
+ ```text
118
+ chivgent [options] "question" Answer one question and exit
119
+ chivgent [options] Start an interactive session
120
+
121
+ Options:
122
+ --provider NAME openai, deepseek, or openai-compatible (default: openai)
123
+ --model MODEL Provider model override
124
+ --max-turns N Tool-calling turn limit (default: 8)
125
+ --no-stream Wait for the full answer instead of streaming tokens
126
+ -q, --quiet Hide tool activity on stderr
127
+ --json Write the run as JSON lines instead of rendered text
128
+ -c, --continue Resume the most recent session for this workspace
129
+ --resume ID Resume a specific session
130
+ --sessions List recorded sessions and exit
131
+ --no-session Do not record this run
132
+ -h, --help Show help
133
+ -v, --version Show version
134
+ ```
135
+
136
+ In an interactive session, `/help` lists the slash commands: `/session`,
137
+ `/tools`, `/clear`, and `/exit`. Ctrl+C stops the answer in progress without
138
+ leaving the session; Ctrl+D leaves it.
139
+
140
+ Exit codes: `0` answered, `1` configuration or Provider failure, `2` turn limit
141
+ reached, `130` interrupted with Ctrl+C.
142
+
143
+ ### Provider configuration
144
+
145
+ | Provider | API key | Model environment variable | Default model | API style |
146
+ | --- | --- | --- | --- | --- |
147
+ | OpenAI | `OPENAI_API_KEY` | `OPENAI_MODEL` | `gpt-5.6` | Responses API |
148
+ | DeepSeek | `DEEPSEEK_API_KEY` | `DEEPSEEK_MODEL` | `deepseek-v4-flash` | OpenAI-compatible Chat Completions |
149
+ | Custom compatible | `OPENAI_API_KEY` | `OPENAI_MODEL` | Required | OpenAI-compatible Chat Completions |
150
+
151
+ An explicit `--model` value takes precedence over the Provider-specific model
152
+ environment variable. Custom compatible Providers also require
153
+ `OPENAI_BASE_URL`. Sessions are written under `CHIVGENT_HOME` (default
154
+ `~/.chivgent`).
155
+
156
+ ```bash
157
+ chivgent --provider openai --model gpt-5.6 "Explain package.json"
158
+ chivgent --provider deepseek --model deepseek-v4-pro "Explain package.json"
159
+ chivgent --provider openai-compatible --model vendor-model "Explain package.json"
160
+ ```
161
+
162
+ ## Architecture
163
+
164
+ ```text
165
+ +-> OpenAI Responses API
166
+ User -> CLI -> Agent -> LLMClient |
167
+ | +-> OpenAI-compatible Chat -> DeepSeek / custom
168
+ |
169
+ +-> Tool Registry -> list_files / search_text / read_file -> Workspace
170
+ ```
171
+
172
+ The Agent runtime owns its own messages. Provider-specific schemas are converted
173
+ only at the `LLMClient` boundary:
174
+
175
+ ```text
176
+ Agent Message[] -> Provider adapter -> Provider request
177
+ <- Provider response
178
+ AssistantMessage <- normalized result
179
+ ```
180
+
181
+ This prevents the Agent, tools, and CLI from depending on one vendor's message
182
+ format.
183
+
184
+ ### Runtime events
185
+
186
+ The Agent Loop reports what it is doing through a typed event stream instead of
187
+ printing anything itself. One run emits:
188
+
189
+ ```text
190
+ agent_start
191
+ turn_start -> message_start -> message_update* -> message_end
192
+ tool_execution_start -> tool_execution_end (once per tool call)
193
+ turn_end
194
+ ...
195
+ agent_end (completed | max_turns | aborted | error)
196
+ ```
197
+
198
+ `message_update` carries deltas only, never a cumulative snapshot, so the stream
199
+ stays linear in the length of the answer. Events are structured-cloneable and
200
+ each listener receives a copy, so a renderer can never mutate the transcript.
201
+ The CLI renderer in `src/render.ts` is one consumer; a log file, a JSON stream,
202
+ or a TUI are others.
203
+
204
+ `LLMClient.stream` is optional. When a Provider does not implement it, the Agent
205
+ falls back to `complete` and the same events are emitted without deltas.
206
+
207
+ ### OpenAI-compatible Providers
208
+
209
+ Compatible Providers reuse the official `openai` npm package by changing
210
+ `baseURL`, credentials, and model. CLI users do not need to edit code:
211
+
212
+ ```bash
213
+ export OPENAI_API_KEY="your-provider-api-key"
214
+ export OPENAI_BASE_URL="https://api.vendor.example/v1"
215
+ export OPENAI_MODEL="vendor-model"
216
+
217
+ chivgent --provider openai-compatible "What does src/agent.ts do?"
218
+ ```
219
+
220
+ `OPENAI_BASE_URL` must point to the Provider's OpenAI-compatible API root. The
221
+ Provider must implement `POST /chat/completions` and function tool calling.
222
+
223
+ When adding a named Provider in source code, use the same adapter:
224
+
225
+ ```ts
226
+ const client = new OpenAICompatibleChatClient({
227
+ apiKey: process.env.VENDOR_API_KEY!,
228
+ baseURL: "https://api.vendor.example/v1",
229
+ model: "vendor-model",
230
+ continuationTag: "vendor-chat",
231
+ });
232
+ ```
233
+
234
+ `DeepSeekChatClient` is a small configuration wrapper around this shared client.
235
+ The compatibility layer also preserves optional Provider-only fields such as
236
+ DeepSeek's `reasoning_content` inside opaque continuation state.
237
+
238
+ Changing only `baseURL` is not a promise of complete compatibility. Providers
239
+ can differ in model names, authentication, tool-schema support, strict mode,
240
+ reasoning fields, streaming events, and error behavior. Keep those differences
241
+ inside thin Provider adapters rather than leaking them into the Agent loop.
242
+
243
+ ## Project structure
244
+
245
+ ```text
246
+ src/
247
+ cli.ts CLI entry point and process boundary
248
+ cli-options.ts Argument and Provider configuration
249
+ agent.ts Agent loop and run state
250
+ events.ts Runtime event model
251
+ render.ts Terminal renderer for runtime events
252
+ llm.ts Provider-independent LLM contract
253
+ retry.ts Provider timeout and retry decorator
254
+ messages.ts Runtime message model
255
+ session.ts Conversation state and event fan-out
256
+ session-store.ts JSONL session log and resume support
257
+ repl.ts Interactive prompt and slash commands
258
+ workspace.ts Safe local workspace access
259
+ providers/
260
+ openai.ts OpenAI Responses adapter
261
+ openai-compatible-chat.ts Shared Chat Completions adapter
262
+ deepseek.ts DeepSeek configuration wrapper
263
+ tools/
264
+ tool.ts Tool contract
265
+ output.ts Shared 64 KiB tool-output boundary
266
+ list-files.ts Deterministic project-tree discovery
267
+ search-text.ts Bounded literal source search
268
+ read-file.ts Ranged text-file reader
269
+ tests/ Provider, loop, and workspace tests
270
+ docs/ Architecture and learning notes
271
+ ```
272
+
273
+ ## Development
274
+
275
+ ```bash
276
+ npm install
277
+ npm run check
278
+ npm test
279
+ npm run build
280
+ ```
281
+
282
+ Run the complete release gate, including an npm tarball dry run:
283
+
284
+ ```bash
285
+ npm run release:check
286
+ ```
287
+
288
+ Build a locally installable tarball:
289
+
290
+ ```bash
291
+ npm pack
292
+ npm install -g ./chivgent-0.6.0.tgz
293
+ ```
294
+
295
+ Tests use scripted or mocked LLM clients. A real API smoke test is deliberately
296
+ manual so the default test suite never consumes credits.
297
+
298
+ ## Security model
299
+
300
+ - API keys are read from environment variables and must never be committed.
301
+ - A custom `OPENAI_BASE_URL` receives the configured API key and prompts; use
302
+ only endpoints you trust.
303
+ - All current workspace tools are read-only.
304
+ - Paths must remain inside the current workspace.
305
+ - Real-path checks block `..` traversal and symlink escapes.
306
+ - File size and binary-content checks limit unsafe reads.
307
+ - Discovery respects the root `.gitignore` and fixed generated-directory ignores.
308
+ - Common credential and private-key paths are denied across all workspace tools.
309
+ - Tool results are limited to 64 KiB; reads, scans, depth, and result counts are bounded.
310
+ - Tool inputs are untrusted and validated before execution.
311
+ - The agent stops after a bounded number of model turns.
312
+ - Session logs under `~/.chivgent/sessions` contain prompts, answers, and tool
313
+ results, including file excerpts. Use `--no-session` in sensitive workspaces,
314
+ and treat the log directory like the project it describes.
315
+ - Session ids are validated before they become file paths.
316
+
317
+ This is an educational MVP, not a hardened sandbox. Review the code and threat
318
+ model before granting future write or shell tools access to sensitive projects.
319
+
320
+ ## Roadmap
321
+
322
+ - [x] Minimal tool-calling agent loop
323
+ - [x] Safe `read_file` tool
324
+ - [x] OpenAI and DeepSeek Providers
325
+ - [x] Reusable OpenAI-compatible Chat Completions adapter
326
+ - [x] Custom OpenAI-compatible CLI Provider
327
+ - [x] Project discovery tools: `list_files`, `search_text`, and ranged `read_file`
328
+ - [x] Streaming output and runtime events
329
+ - [x] Persistent multi-turn sessions
330
+ - [ ] Context-window management and compaction
331
+ - [ ] Permission-gated `write_file`, `edit_file`, and shell tools
332
+ - [ ] Provider registry and user configuration file
333
+ - [ ] TUI, extensions, telemetry, and evals
334
+
335
+ ## Documentation
336
+
337
+ - [Stage 1: Minimal Agent design](docs/stage-1-minimal-agent.md)
338
+ - [DeepSeek Provider design](docs/deepseek-provider.md)
339
+ - [Stage 2: Project Discovery implementation design](docs/stage-2-project-discovery.md)
340
+ - [Stage 3: Runtime Events and Streaming design](docs/stage-3-runtime-events.md)
341
+ - [Stage 4: Sessions and interactive mode design](docs/stage-4-sessions.md)
342
+ - [Release process](docs/releasing.md)
343
+
344
+ ## Contributing
345
+
346
+ Issues and focused pull requests are welcome. Before submitting a change, run:
347
+
348
+ ```bash
349
+ npm run check
350
+ npm test
351
+ npm run build
352
+ ```
353
+
354
+ Please keep Provider-specific types inside `src/providers/` and keep the core
355
+ Agent runtime independent from vendor SDK schemas.
356
+
357
+ ## License
358
+
359
+ Licensed under the [MIT License](LICENSE).