@yachiyo-5i/xlyra-agent 0.2.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.
- package/LICENSE +661 -0
- package/README.md +306 -0
- package/dist/chunk-QH6SEOO6.js +3590 -0
- package/dist/chunk-QH6SEOO6.js.map +1 -0
- package/dist/cli.cjs +3833 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +287 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +3703 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1171 -0
- package/dist/index.d.ts +1171 -0
- package/dist/index.js +145 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>xlyra-agent</h1>
|
|
3
|
+
<p>A general-purpose conversational agent runtime for TypeScript.</p>
|
|
4
|
+
<p>
|
|
5
|
+
<a href="README_zh.md">简体中文</a> ·
|
|
6
|
+
<a href="#quick-start">Quick Start</a> ·
|
|
7
|
+
<a href="LICENSE">License</a>
|
|
8
|
+
</p>
|
|
9
|
+
<p>
|
|
10
|
+
<img src="https://img.shields.io/badge/license-AGPL--3.0-blue.svg" alt="License" />
|
|
11
|
+
<img src="https://img.shields.io/badge/runtime-Node.js%2022%2B-339933.svg" alt="Runtime" />
|
|
12
|
+
<img src="https://img.shields.io/badge/language-TypeScript-3178C6.svg" alt="Language" />
|
|
13
|
+
<img src="https://img.shields.io/badge/protocols-OpenAI%20%7C%20Anthropic-6B5B95.svg" alt="Protocols" />
|
|
14
|
+
</p>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
A streaming agent loop with OpenAI Responses and Anthropic Messages protocol adapters, sandboxed local tools, persistent sessions, and an optional REST/SSE service.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- **Streaming agent loop** — streams reasoning, text, tool calls, tool results, and terminal events through an async generator.
|
|
23
|
+
- **Two LLM protocols** — supports OpenAI Responses and Anthropic Messages over direct HTTP with built-in SSE parsing.
|
|
24
|
+
- **Tool execution** — includes directory listing, file reading and search, file creation and editing, atomic writes, multi-file patches, and managed command processes.
|
|
25
|
+
- **Safe concurrency** — runs consecutive read-only tools in parallel while preserving ordering barriers for writes and commands.
|
|
26
|
+
- **Workspace sandbox** — blocks path traversal and symlink escapes; out-of-workspace access requires session-level approval.
|
|
27
|
+
- **Command approval** — command tools can be pre-authorized or approved per session before execution.
|
|
28
|
+
- **Context compaction** — automatically summarizes history near the model context limit while preserving recent user messages.
|
|
29
|
+
- **Persistent sessions** — stores transcripts as JSONL and rebuilds the session index from the source records on startup.
|
|
30
|
+
- **Resumable streaming** — exposes SSE events with `Last-Event-ID` replay, heartbeats, cancellation, and terminal-state guarantees.
|
|
31
|
+
- **Library and service modes** — use the runtime as an npm library or run it behind the included HTTP service and CLI.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### Requirements
|
|
36
|
+
|
|
37
|
+
- Node.js 22 or later
|
|
38
|
+
- pnpm
|
|
39
|
+
- Bun only when building the standalone executable
|
|
40
|
+
|
|
41
|
+
### Installation
|
|
42
|
+
|
|
43
|
+
For npm users, install the published package globally:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm i -g @yachiyo-5i/xlyra-agent
|
|
47
|
+
xlyra --help
|
|
48
|
+
xlyra config init
|
|
49
|
+
xlyra serve
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The package requires Node.js 22 or later and includes both the library and the `xlyra` CLI. To use it as a library:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm i @yachiyo-5i/xlyra-agent
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
For source development, install dependencies and build locally:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pnpm install
|
|
62
|
+
pnpm build
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The build produces ESM, CommonJS, and TypeScript declarations in `dist/`.
|
|
66
|
+
|
|
67
|
+
To build and install the standalone `xlyra` command locally:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pnpm install:local
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This command requires Bun and links the executable to `~/.local/bin/xlyra`.
|
|
74
|
+
|
|
75
|
+
## Library Usage
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { AgentRunner, EndpointResolver, builtinTools } from "@yachiyo-5i/xlyra-agent";
|
|
79
|
+
|
|
80
|
+
const resolver = new EndpointResolver([
|
|
81
|
+
{
|
|
82
|
+
name: "anthropic",
|
|
83
|
+
protocol: "anthropic-messages",
|
|
84
|
+
base_url: "https://api.anthropic.com",
|
|
85
|
+
api_key: process.env.ANTHROPIC_API_KEY!,
|
|
86
|
+
default_model: "claude-sonnet-4-5",
|
|
87
|
+
},
|
|
88
|
+
]);
|
|
89
|
+
|
|
90
|
+
const runner = new AgentRunner({
|
|
91
|
+
resolver,
|
|
92
|
+
tools: builtinTools({ workdir: "./workspace" }),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
for await (const event of runner.start({
|
|
96
|
+
input: "List the current directory and summarize the README.",
|
|
97
|
+
})) {
|
|
98
|
+
if (event.type === "text_delta") process.stdout.write(event.delta ?? "");
|
|
99
|
+
if (event.type === "agent_done") console.log("\nUsage:", event.result?.usage);
|
|
100
|
+
if (event.type === "agent_error") console.error("Error:", event.error);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
A model can be selected with:
|
|
105
|
+
|
|
106
|
+
- `endpoint/model-id` for an explicit endpoint
|
|
107
|
+
- `model-id` when it resolves to a unique endpoint
|
|
108
|
+
- an empty string to use the first endpoint's default model
|
|
109
|
+
|
|
110
|
+
### Event Stream
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
agent_start
|
|
114
|
+
→ (thinking_delta | text_delta)*
|
|
115
|
+
→ (tool_call_start → tool_call_delta* → tool_call → tool_result*)*
|
|
116
|
+
→ agent_done | agent_error | agent_cancelled
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`context_compacted` and `escalation_request` may appear at safe points during a run.
|
|
120
|
+
|
|
121
|
+
## Service Usage
|
|
122
|
+
|
|
123
|
+
### Configuration
|
|
124
|
+
|
|
125
|
+
The default configuration file is `~/.xlyra-agent/config.json`.
|
|
126
|
+
|
|
127
|
+
Create and manage it with the CLI:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
xlyra config init
|
|
131
|
+
xlyra config add
|
|
132
|
+
xlyra config add openai
|
|
133
|
+
xlyra config list
|
|
134
|
+
xlyra config remove <name>
|
|
135
|
+
xlyra config path
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Interactive configuration commands require a TTY. For automated environments, write the configuration file directly:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"endpoints": [
|
|
143
|
+
{
|
|
144
|
+
"name": "anthropic",
|
|
145
|
+
"protocol": "anthropic-messages",
|
|
146
|
+
"base_url": "https://api.anthropic.com",
|
|
147
|
+
"api_key": "${ANTHROPIC_API_KEY}",
|
|
148
|
+
"default_model": "claude-sonnet-4-5",
|
|
149
|
+
"models": {
|
|
150
|
+
"claude-sonnet-4-5": {
|
|
151
|
+
"context_window": 200000
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "openai",
|
|
157
|
+
"protocol": "openai-responses",
|
|
158
|
+
"base_url": "https://api.openai.com/v1",
|
|
159
|
+
"api_key": "${OPENAI_API_KEY}",
|
|
160
|
+
"default_model": "gpt-5"
|
|
161
|
+
}
|
|
162
|
+
],
|
|
163
|
+
"server": {
|
|
164
|
+
"port": 3210,
|
|
165
|
+
"token": "replace-with-a-long-random-token"
|
|
166
|
+
},
|
|
167
|
+
"agent": {
|
|
168
|
+
"workdir": "~/.xlyra-agent/workspace",
|
|
169
|
+
"agent_name": "xlyra assistant",
|
|
170
|
+
"persona": "A concise software engineering assistant",
|
|
171
|
+
"enable_command_execution": false
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
API keys support `${ENV_VAR}` interpolation. Configuration is validated at startup, and configuration writes use atomic replacement.
|
|
177
|
+
|
|
178
|
+
### Start the Server
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
pnpm dev:serve
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Or start the built CLI:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
node dist/cli.js serve --port 3210
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
After global npm installation, the equivalent command is:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
xlyra serve --port 3210
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Runtime data is stored under `~/.xlyra-agent/`:
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
~/.xlyra-agent/
|
|
200
|
+
├── config.json
|
|
201
|
+
├── index.json
|
|
202
|
+
├── sessions/
|
|
203
|
+
└── workspace/
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### HTTP API
|
|
207
|
+
|
|
208
|
+
| Method | Path | Description |
|
|
209
|
+
|---|---|---|
|
|
210
|
+
| `POST` | `/sessions` | Start a session or continue an existing session |
|
|
211
|
+
| `GET` | `/sessions` | List recent sessions with pagination |
|
|
212
|
+
| `GET` | `/sessions/:id/transcript` | Read the complete transcript and compaction records |
|
|
213
|
+
| `PATCH` | `/sessions/:id` | Rename a session |
|
|
214
|
+
| `DELETE` | `/sessions/:id` | Delete an idle session |
|
|
215
|
+
| `POST` | `/sessions/:id/retry` | Retry from a selected user message |
|
|
216
|
+
| `POST` | `/sessions/:id/compact-context` | Compact the current model context manually |
|
|
217
|
+
| `POST` | `/sessions/:id/grant-access` | Approve or reject a path or command escalation |
|
|
218
|
+
| `GET` | `/sessions/:id/events` | Follow events over SSE with replay support |
|
|
219
|
+
| `POST` | `/sessions/:id/stop` | Stop the active run idempotently |
|
|
220
|
+
| `GET` | `/health` | Check service health |
|
|
221
|
+
| `GET` | `/config` | Read the configuration with masked API keys |
|
|
222
|
+
| `PUT` | `/config` | Validate and save the configuration |
|
|
223
|
+
| `POST` | `/config/test` | Test an endpoint with a minimal model request |
|
|
224
|
+
|
|
225
|
+
When `server.token` is configured, requests must include:
|
|
226
|
+
|
|
227
|
+
```http
|
|
228
|
+
Authorization: Bearer <token>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Without a token, the service is unauthenticated and must not be exposed to untrusted networks.
|
|
232
|
+
|
|
233
|
+
## Built-in Tools
|
|
234
|
+
|
|
235
|
+
| Tool | Description |
|
|
236
|
+
|---|---|
|
|
237
|
+
| `list` | List files and directories with recursion and glob support |
|
|
238
|
+
| `read` | Read text files in bounded chunks |
|
|
239
|
+
| `search` | Search file contents and return matching paths and lines |
|
|
240
|
+
| `create` | Create a new file and fail if the target already exists |
|
|
241
|
+
| `edit` | Replace exact text with optional explicit multi-match replacement |
|
|
242
|
+
| `write` | Atomically overwrite an existing file |
|
|
243
|
+
| `apply_patch` | Validate and apply a multi-file patch as one operation |
|
|
244
|
+
| `exec_command` | Execute an argv-based local command and manage long-running processes |
|
|
245
|
+
| `write_stdin` | Poll a command session or write data to its standard input |
|
|
246
|
+
|
|
247
|
+
File tools are restricted to the configured workspace by default. The sandbox checks resolved paths and symlinks. Access outside the workspace can be approved for the current session.
|
|
248
|
+
|
|
249
|
+
Command execution is declared to the model but is not pre-authorized unless `enableCommandExecution: true` or `agent.enable_command_execution: true` is configured. Commands are launched directly from argv without an implicit shell, with workspace-checked cwd, bounded output, timeout, and AbortSignal cancellation. Child processes still inherit the operating-system permissions of the current user; production deployments should additionally use containers, a dedicated OS user, or another OS-level sandbox.
|
|
250
|
+
|
|
251
|
+
## Persistence and Recovery
|
|
252
|
+
|
|
253
|
+
- Each session is stored as an append-oriented JSONL transcript.
|
|
254
|
+
- Final messages, tool results, compaction records, and escalation records are persisted.
|
|
255
|
+
- Interrupted tool calls receive a synthetic error result so recovered history remains valid.
|
|
256
|
+
- `index.json` is a query index, not the source of truth; it is rebuilt from session files at startup.
|
|
257
|
+
- Configuration, indexes, retries, escalation updates, and file writes use temporary files followed by atomic rename where applicable.
|
|
258
|
+
|
|
259
|
+
## Testing
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
pnpm test
|
|
263
|
+
pnpm typecheck
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The default test suite is offline and covers protocol adapters, SSE parsing, the agent loop, context compaction, persistence, tools, REST/SSE routes, configuration, and CLI behavior.
|
|
267
|
+
|
|
268
|
+
Run smoke tests against configured model endpoints with:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
pnpm test:smoke
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Optional environment variables:
|
|
275
|
+
|
|
276
|
+
```text
|
|
277
|
+
XLYRA_SMOKE_CONFIG=<config-path>
|
|
278
|
+
XLYRA_SMOKE_ENDPOINT=<endpoint-name>
|
|
279
|
+
OPENAI_API_KEY=<key>
|
|
280
|
+
OPENAI_MODEL=<model>
|
|
281
|
+
ANTHROPIC_API_KEY=<key>
|
|
282
|
+
ANTHROPIC_MODEL=<model>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Smoke tests make real model requests and may incur provider charges.
|
|
286
|
+
|
|
287
|
+
## Publishing with GitHub Actions
|
|
288
|
+
|
|
289
|
+
The repository includes CI verification, Release Please, and a GitHub Release-triggered npm publishing workflow. Publishing uses npm Trusted Publishing with GitHub OIDC, so no long-lived npm token is stored in GitHub.
|
|
290
|
+
|
|
291
|
+
Before the first release:
|
|
292
|
+
|
|
293
|
+
1. Push the repository and these workflows to `main`.
|
|
294
|
+
2. On npm, add a Trusted Publisher for package `@yachiyo-5i/xlyra-agent`:
|
|
295
|
+
- GitHub owner: `Yachiyo-5i`
|
|
296
|
+
- Repository: `xLyra-agent`
|
|
297
|
+
- Workflow file: `.github/workflows/publish-npm.yml`
|
|
298
|
+
- Environment: `npm`
|
|
299
|
+
3. In GitHub, create the `npm` environment. Require approval for this environment if releases should be manually reviewed.
|
|
300
|
+
4. Configure branch protection for `main` as described above.
|
|
301
|
+
5. Merge regular feature PRs into `main`. Release Please will create or update the release PR.
|
|
302
|
+
6. Review and merge the Release Please PR. It creates the GitHub Release, which triggers npm publication.
|
|
303
|
+
|
|
304
|
+
The publish workflow runs typecheck, tests, build, and package-content checks before publishing. It cannot publish the same package version twice; versions are managed by Release Please from Conventional Commits.
|
|
305
|
+
|
|
306
|
+
xLyra Agent is licensed under the [GNU Affero General Public License v3.0](LICENSE).
|