zyn-ai 1.3.7 → 1.4.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/README.md +153 -92
- package/package.json +22 -11
- package/src/agent.js +168 -0
- package/src/cli/commands.js +459 -164
- package/src/cli/print.js +34 -0
- package/src/cli/runtime.js +122 -26
- package/src/cli/selector.js +223 -0
- package/src/config.js +134 -33
- package/src/core/agent.js +119 -223
- package/src/core/prompts.js +181 -123
- package/src/core/skills.js +166 -59
- package/src/i18n.js +0 -14
- package/src/platforms/baileys.js +75 -0
- package/src/platforms/discord.js +66 -0
- package/src/platforms/index.js +28 -0
- package/src/platforms/telegram.js +55 -0
- package/src/providers/catalog.js +216 -22
- package/src/providers/custom/index.js +92 -0
- package/src/providers/deepseek/index.js +317 -0
- package/src/providers/deepseek/sha3_wasm_bg.wasm +0 -0
- package/src/providers/gemini/index.js +117 -337
- package/src/providers/huggingface/index.js +149 -0
- package/src/providers/qwenapi/index.js +132 -0
- package/src/providers/scraperClient.js +27 -10
- package/src/providers/zen/index.js +84 -56
- package/src/public/helpers.js +25 -0
- package/src/tools/index.js +301 -146
- package/src/tui/app.mjs +685 -114
- package/src/utils/backgroundWorker.js +116 -0
- package/src/utils/sessionStorage.js +92 -7
- package/src/web/server.js +54 -1
- package/src/web/store.js +23 -0
- package/src/web/webAgent.js +2 -2
package/README.md
CHANGED
|
@@ -8,45 +8,41 @@
|
|
|
8
8
|
<img src="https://img.shields.io/npm/v/zyn-ai?label=npm&color=%23CB3837" alt="NPM Version"/>
|
|
9
9
|
<img src="https://img.shields.io/github/v/release/SoyMaycol/Zyn?include_prereleases&sort=semver" alt="Latest Release"/>
|
|
10
10
|
<img src="https://img.shields.io/npm/dt/zyn-ai" alt="Downloads"/>
|
|
11
|
+
<img src="https://img.shields.io/github/license/SoyMaycol/Zyn" alt="License"/>
|
|
11
12
|
</p>
|
|
12
13
|
|
|
13
14
|
<p align="center">
|
|
14
|
-
<b>
|
|
15
|
+
<b>A complete CLI Agent for production and enterprise level, with incredible results.</b>
|
|
15
16
|
</p>
|
|
16
17
|
|
|
17
18
|
<p align="center">
|
|
18
|
-
<a href="https://github.com/SoyMaycol/Zyn">
|
|
19
|
+
<a href="https://github.com/SoyMaycol/Zyn">GitHub</a>
|
|
19
20
|
</p>
|
|
20
21
|
|
|
21
22
|
---
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
> Using the web version of the agent is not recommended as it contains bugs. I am doing my best to fix most of the web bugs.
|
|
24
|
+
## Features
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
- npm
|
|
36
|
-
- Internet connection for remote providers
|
|
26
|
+
- **CLI + TUI** — full terminal UI with keyboard navigation, token display, **improved history & compaction**, overlay system
|
|
27
|
+
- **Multi-provider** — Zen (free, no config), Gemini, Qwen (DashScope), HuggingFace, **skill search**, custom providers (any OpenAI-compatible API)
|
|
28
|
+
- **Skills system** — folder-based skills with **improved prompt integration** and YAML frontmatter
|
|
29
|
+
- **Tool execution** — read/write files, run commands, search code, browse web, glob patterns
|
|
30
|
+
- **Session management** — **real conversation history**, persistent sessions with **better compaction**, full transcript replay, resume, export
|
|
31
|
+
- **Context tracking** — token estimator with per-model context limits, **auto-compaction at 85%**, updated to reflect new history behavior
|
|
32
|
+
- **Multi-platform** — embeddable in WhatsApp (Baileys), Discord, and Telegram bots, Although this function is not complete (It is under development)
|
|
33
|
+
- **Background workers** — detach long-running turns to background processes
|
|
34
|
+
- **i18n** — English and Spanish interfaces
|
|
37
35
|
|
|
38
36
|
---
|
|
39
37
|
|
|
40
38
|
## Installation
|
|
41
39
|
|
|
42
|
-
### Global install
|
|
43
|
-
|
|
44
40
|
```bash
|
|
45
41
|
npm install -g zyn-ai
|
|
46
42
|
zyn
|
|
47
43
|
```
|
|
48
44
|
|
|
49
|
-
###
|
|
45
|
+
### From source
|
|
50
46
|
|
|
51
47
|
```bash
|
|
52
48
|
git clone https://github.com/SoyMaycol/Zyn.git
|
|
@@ -55,125 +51,190 @@ npm install
|
|
|
55
51
|
npm start
|
|
56
52
|
```
|
|
57
53
|
|
|
58
|
-
---
|
|
59
|
-
|
|
60
54
|
## Usage
|
|
61
55
|
|
|
62
56
|
```bash
|
|
63
|
-
zyn
|
|
64
|
-
zyn "
|
|
65
|
-
zyn --new
|
|
66
|
-
zyn --resume ID
|
|
57
|
+
zyn # Interactive TUI (default)
|
|
58
|
+
zyn "question" # Single prompt (CLI mode)
|
|
59
|
+
zyn --new # Force new session
|
|
60
|
+
zyn --resume ID # Resume existing session (keeps history)
|
|
67
61
|
```
|
|
68
62
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
## Web mode
|
|
63
|
+
## Models
|
|
72
64
|
|
|
73
|
-
|
|
65
|
+
14 built-in models across 4 providers. Each model has its real context length in the StatusBar (e.g. `10.8K/128K`).
|
|
74
66
|
|
|
75
|
-
|
|
76
|
-
/web
|
|
77
|
-
/web 0.0.0.0:3000
|
|
78
|
-
```
|
|
67
|
+
### Zen (free, no configuration)
|
|
79
68
|
|
|
80
|
-
|
|
69
|
+
| Key | Model | Context |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `nemotron` | Nemotron 3 Ultra | 128K |
|
|
72
|
+
| `mimo` | Mimo 2.5 | 128K |
|
|
73
|
+
| `north-mini` | North Mini Code | 128K |
|
|
74
|
+
| `deepseek` | DeepSeek V4 Flash | 128K |
|
|
81
75
|
|
|
82
|
-
|
|
83
|
-
npm run web
|
|
84
|
-
```
|
|
76
|
+
### Gemini (requires API key)
|
|
85
77
|
|
|
86
|
-
|
|
78
|
+
| Key | Model | Context |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `gemini-flash` | Gemini 2.5 Flash | 1M |
|
|
81
|
+
| `gemini-flash-001` | Gemini 2.5 Flash 001 | 1M |
|
|
82
|
+
| `gemini-pro` | Gemini 2.5 Pro | 1M |
|
|
83
|
+
| `gemini-flash-lite` | Gemini 2.5 Flash Lite | 1M |
|
|
84
|
+
| `gemini-flash-lite-001` | Gemini 2.5 Flash Lite 001 | 1M |
|
|
85
|
+
| `gemma-3` | Gemma 3 27B | 128K |
|
|
87
86
|
|
|
88
|
-
|
|
87
|
+
### Qwen (requires DashScope API key)
|
|
89
88
|
|
|
90
|
-
|
|
89
|
+
| Key | Model | Context |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `qwen-plus` | Qwen Plus | 128K |
|
|
92
|
+
| `qwen-max` | Qwen Max | 32K |
|
|
93
|
+
| `qwen-turbo` | Qwen Turbo | 1M |
|
|
91
94
|
|
|
92
|
-
|
|
93
|
-
- `es`
|
|
95
|
+
### HuggingFace (requires HF token)
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
| Key | Model | Context |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `hf-ling-2.6-1t` | InclusionAI Ling 2.6 1T | 128K |
|
|
96
100
|
|
|
97
|
-
|
|
98
|
-
/lang
|
|
99
|
-
/lang en
|
|
100
|
-
/lang es
|
|
101
|
-
```
|
|
101
|
+
Default model: `nemotron` (Zen, no configuration required).
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
## Main Commands
|
|
103
|
+
## Commands
|
|
106
104
|
|
|
107
105
|
### Sessions
|
|
108
106
|
|
|
109
107
|
| Command | Description |
|
|
110
108
|
|---|---|
|
|
111
|
-
| `/help` | Show
|
|
112
|
-
| `/status` |
|
|
113
|
-
| `/history` |
|
|
114
|
-
| `/memory` |
|
|
115
|
-
| `/
|
|
116
|
-
| `/
|
|
117
|
-
| `/
|
|
109
|
+
| `/help` | Show help |
|
|
110
|
+
| `/status` | Current status |
|
|
111
|
+
| `/history` | Recent actions (last 20) |
|
|
112
|
+
| `/memory` | Memory summary |
|
|
113
|
+
| `/session` | Current session info |
|
|
114
|
+
| `/sessions` | List all sessions |
|
|
115
|
+
| `/new` | New session |
|
|
116
|
+
| `/resume <ID>` | Resume session (keeps history) |
|
|
118
117
|
| `/title <text>` | Rename session |
|
|
119
118
|
|
|
120
119
|
### Configuration
|
|
121
120
|
|
|
122
121
|
| Command | Description |
|
|
123
122
|
|---|---|
|
|
124
|
-
| `/
|
|
125
|
-
| `/
|
|
126
|
-
| `/
|
|
123
|
+
| `/models` | Open model picker (current provider) |
|
|
124
|
+
| `/providers` | Open interactive provider picker → configure → pick model |
|
|
125
|
+
| `/provider list` | List configured providers and their fields |
|
|
126
|
+
| `/provider sync <name>` | Fetch models from a provider's API |
|
|
127
|
+
| `/provider set <name> <field> <value>` | Set provider config (apiKey, baseUrl, modelId, contextLength) |
|
|
128
|
+
| `/provider remove <name>` | Remove a provider configuration |
|
|
127
129
|
| `/lang <en\|es>` | Change language |
|
|
130
|
+
| `/auto on\|off` | Toggle auto-approval |
|
|
131
|
+
| `/concuerdo` | Toggle group model mode (queries all configured models) |
|
|
132
|
+
| `/persona set <text>` | Set response persona |
|
|
128
133
|
| `/config show` | Show config |
|
|
129
|
-
| `/
|
|
134
|
+
| `/git set\|list\|remove` | Manage git credentials |
|
|
130
135
|
| `/cwd <path>` | Change working directory |
|
|
131
136
|
|
|
132
|
-
### Tools
|
|
137
|
+
### Tools & Skills
|
|
133
138
|
|
|
134
139
|
| Command | Description |
|
|
135
140
|
|---|---|
|
|
136
|
-
| `/tools` | List tools |
|
|
137
|
-
| `/skills` | List skills |
|
|
138
|
-
| `/gmail connect` | Connect Gmail
|
|
139
|
-
| `/gmail status` | Show Gmail connection status |
|
|
140
|
-
| `/gmail disconnect` | Remove saved Gmail tokens |
|
|
141
|
-
| `/cwd` | Show working directory |
|
|
141
|
+
| `/tools` | List agent tools |
|
|
142
|
+
| `/skills` | List loaded skills |
|
|
143
|
+
| `/gmail connect` | Connect Gmail via OAuth |
|
|
142
144
|
|
|
143
|
-
###
|
|
145
|
+
### Export & Control
|
|
144
146
|
|
|
145
147
|
| Command | Description |
|
|
146
148
|
|---|---|
|
|
147
|
-
| `/
|
|
148
|
-
| `/transcript` |
|
|
149
|
-
| `/export` | Export session |
|
|
149
|
+
| `/bg` | Detach current turn to background |
|
|
150
|
+
| `/transcript` | View session transcript |
|
|
151
|
+
| `/export` | Export session to txt |
|
|
152
|
+
| `/stop` | Stop current agent turn |
|
|
153
|
+
| `/undo` | Undo last turn |
|
|
154
|
+
| `/redo` | Redo undone turn |
|
|
155
|
+
| `/reset` | Reset context |
|
|
156
|
+
| `/exit` | Exit |
|
|
150
157
|
|
|
151
|
-
|
|
158
|
+
Press `ESC` twice in the TUI to stop the current task.
|
|
152
159
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
| `/reset` | Reset session |
|
|
157
|
-
| `/exit` | Exit Zyn |
|
|
160
|
+
## Custom Providers
|
|
161
|
+
|
|
162
|
+
Add any OpenAI-compatible API:
|
|
158
163
|
|
|
159
|
-
|
|
164
|
+
```bash
|
|
165
|
+
# Interactive: run /providers → select "+ Add custom provider"
|
|
166
|
+
# Or manual:
|
|
167
|
+
/provider set groq baseUrl https://api.groq.com/openai/v1
|
|
168
|
+
/provider set groq apiKey gsk_xxxx
|
|
169
|
+
/provider set groq contextLength 128000
|
|
170
|
+
/provider sync groq
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Configurable fields: `apiKey`, `baseUrl`, `modelId`, `contextLength`, `email`, `password`, `modelEndpoint`, `chatEndpoint`.
|
|
160
174
|
|
|
175
|
+
## Skills
|
|
176
|
+
|
|
177
|
+
Skills are folders under `data/skills/<name>/SKILL.md` with YAML frontmatter:
|
|
178
|
+
|
|
179
|
+
```markdown
|
|
180
|
+
---
|
|
181
|
+
name: reasoning
|
|
182
|
+
description: Reasoning and planning for complex tasks
|
|
161
183
|
---
|
|
162
184
|
|
|
163
|
-
|
|
185
|
+
# Skill body here
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The system prompt automatically advertises every loaded skill to the model, and mentions of GitHub repos/skills trigger `web_search` to find them.
|
|
189
|
+
|
|
190
|
+
## API
|
|
191
|
+
|
|
192
|
+
### Embed in your bot
|
|
164
193
|
|
|
165
|
-
|
|
194
|
+
```js
|
|
195
|
+
const { createAgent } = require('zyn-ai');
|
|
166
196
|
|
|
167
|
-
|
|
197
|
+
const agent = createAgent({
|
|
198
|
+
model: 'nemotron',
|
|
199
|
+
language: 'en',
|
|
200
|
+
autoApprove: false,
|
|
201
|
+
});
|
|
168
202
|
|
|
169
|
-
|
|
170
|
-
{
|
|
171
|
-
"models": {
|
|
172
|
-
"my-gemini-flash": {
|
|
173
|
-
"label": "Gemini Flash",
|
|
174
|
-
"provider": "gemini",
|
|
175
|
-
"geminiModel": "gemini-flash"
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
203
|
+
const response = await agent.send('userId', 'Hello!');
|
|
179
204
|
```
|
|
205
|
+
|
|
206
|
+
### Platforms
|
|
207
|
+
|
|
208
|
+
```js
|
|
209
|
+
const { createAgent, platforms } = require('zyn-ai');
|
|
210
|
+
|
|
211
|
+
const agent = createAgent({ model: 'nemotron' });
|
|
212
|
+
|
|
213
|
+
// WhatsApp (Baileys)
|
|
214
|
+
await platforms.whatsapp({ agent, session: './whatsapp-auth' });
|
|
215
|
+
|
|
216
|
+
// Discord
|
|
217
|
+
await platforms.discord({ agent, token: 'DISCORD_TOKEN' });
|
|
218
|
+
|
|
219
|
+
// Telegram
|
|
220
|
+
await platforms.telegram({ agent, token: 'TELEGRAM_TOKEN' });
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Install the corresponding `optionalDependencies` only if you need them.
|
|
224
|
+
|
|
225
|
+
## Environment Variables
|
|
226
|
+
|
|
227
|
+
| Variable | Description |
|
|
228
|
+
|---|---|
|
|
229
|
+
| `ZYN_DEFAULT_MODEL` | Override default model key |
|
|
230
|
+
| `ZYN_DEFAULT_LANG` | Default language (`en` or `es`) |
|
|
231
|
+
| `ZYN_GEMINI_API_KEY` | Gemini API key |
|
|
232
|
+
| `ZYN_QWEN_API_KEY` | DashScope API key |
|
|
233
|
+
| `ZYN_HUGGINGFACE_TOKEN` | HuggingFace token |
|
|
234
|
+
| `ZYN_REQUEST_TIMEOUT_MS` | Request timeout (default: 180000) |
|
|
235
|
+
| `ZYN_PROVIDER_TIMEOUT_MAX_ATTEMPTS` | Retry attempts on provider failure (default: 3) |
|
|
236
|
+
| `ZYN_GMAIL_CLIENT_SECRET` | Gmail OAuth client secret |
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
MIT - Maycol B.T
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zyn-ai",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Production-ready AI agent for CLI and
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "Production-ready AI agent for CLI, TUI, and external platforms (WhatsApp/Baileys, Discord, Telegram) with real tool execution and automation",
|
|
5
5
|
"author": "Maycol",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"ai-agent",
|
|
@@ -14,7 +14,12 @@
|
|
|
14
14
|
"productivity-tool",
|
|
15
15
|
"local-ai-agent",
|
|
16
16
|
"command-line-ai",
|
|
17
|
-
"
|
|
17
|
+
"tui-agent",
|
|
18
|
+
"whatsapp-bot",
|
|
19
|
+
"discord-bot",
|
|
20
|
+
"telegram-bot",
|
|
21
|
+
"multi-platform",
|
|
22
|
+
"embeddable-agent",
|
|
18
23
|
"zyn"
|
|
19
24
|
],
|
|
20
25
|
"bin": {
|
|
@@ -22,22 +27,23 @@
|
|
|
22
27
|
"Zyn": "./zyn.js"
|
|
23
28
|
},
|
|
24
29
|
"type": "commonjs",
|
|
30
|
+
"main": "./src/agent.js",
|
|
25
31
|
"scripts": {
|
|
26
32
|
"start": "node zyn.js",
|
|
27
33
|
"dev": "node zyn.js",
|
|
28
|
-
"
|
|
29
|
-
"check": "node --check zyn.js && node --check src/cli/runtime.js"
|
|
34
|
+
"check": "node --check zyn.js && node --check src/cli/runtime.js && node --check src/agent.js"
|
|
30
35
|
},
|
|
31
36
|
"dependencies": {
|
|
32
37
|
"axios": "^1.7.9",
|
|
33
|
-
"bcryptjs": "^3.0.3",
|
|
34
38
|
"cheerio": "^1.2.0",
|
|
35
|
-
"express": "^5.2.1",
|
|
36
|
-
"express-session": "^1.19.0",
|
|
37
39
|
"ink": "^6.8.0",
|
|
38
40
|
"react": "^19.0.0",
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
+
"jimp": "^0.16.1"
|
|
42
|
+
},
|
|
43
|
+
"optionalDependencies": {
|
|
44
|
+
"@whiskeysockets/baileys": "^6.7.0",
|
|
45
|
+
"discord.js": "^14.16.0",
|
|
46
|
+
"node-telegram-bot-api": "^0.66.0"
|
|
41
47
|
},
|
|
42
48
|
"repository": {
|
|
43
49
|
"type": "git",
|
|
@@ -58,7 +64,12 @@
|
|
|
58
64
|
"LICENSE"
|
|
59
65
|
],
|
|
60
66
|
"exports": {
|
|
61
|
-
".": "./
|
|
67
|
+
".": "./src/agent.js",
|
|
68
|
+
"./agent": "./src/agent.js",
|
|
69
|
+
"./platforms": "./src/platforms/index.js",
|
|
70
|
+
"./platforms/baileys": "./src/platforms/baileys.js",
|
|
71
|
+
"./platforms/discord": "./src/platforms/discord.js",
|
|
72
|
+
"./platforms/telegram": "./src/platforms/telegram.js"
|
|
62
73
|
},
|
|
63
74
|
"preferGlobal": true
|
|
64
75
|
}
|
package/src/agent.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
const { EventEmitter } = require('events');
|
|
2
|
+
const { runAgentTurn } = require('./core/agent');
|
|
3
|
+
const { createNewSessionState, loadSessionState, loadOrCreateSessionState, listSessions, saveState } = require('./utils/sessionStorage');
|
|
4
|
+
const { MODELS, DEFAULT_MODEL_KEY, DEFAULT_LANGUAGE } = require('./config');
|
|
5
|
+
const { listSkills, listModels } = require('./public/helpers');
|
|
6
|
+
const { runBackgroundWorker, detachBackgroundTurn } = require('./utils/backgroundWorker');
|
|
7
|
+
const { enqueueBackgroundTask, listBackgroundResults, consumeBackgroundResult } = require('./utils/sessionStorage');
|
|
8
|
+
|
|
9
|
+
function noopUi() {
|
|
10
|
+
return {
|
|
11
|
+
beginThinkingStream() {},
|
|
12
|
+
writeThinkingDelta() {},
|
|
13
|
+
endThinkingStream() {},
|
|
14
|
+
beginAssistantStream() {},
|
|
15
|
+
writeAssistantDelta() {},
|
|
16
|
+
endAssistantStream() {},
|
|
17
|
+
startThinkingIndicator() { return () => {}; },
|
|
18
|
+
pushAction() {},
|
|
19
|
+
logEvent() {},
|
|
20
|
+
paint: (text) => text,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function createAgent(options = {}) {
|
|
25
|
+
const emitter = new EventEmitter();
|
|
26
|
+
emitter.setMaxListeners(50);
|
|
27
|
+
|
|
28
|
+
const config = {
|
|
29
|
+
sessionId: options.sessionId || null,
|
|
30
|
+
cwd: options.cwd || process.cwd(),
|
|
31
|
+
model: options.model || DEFAULT_MODEL_KEY,
|
|
32
|
+
language: options.language || DEFAULT_LANGUAGE,
|
|
33
|
+
autoApprove: options.autoApprove !== undefined ? Boolean(options.autoApprove) : true,
|
|
34
|
+
personaPrompt: options.personaPrompt || '',
|
|
35
|
+
userId: options.userId || 'default',
|
|
36
|
+
resume: options.resume || false,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let state = null;
|
|
40
|
+
let initPromise = null;
|
|
41
|
+
|
|
42
|
+
async function ensureState() {
|
|
43
|
+
if (state) return state;
|
|
44
|
+
if (!initPromise) {
|
|
45
|
+
initPromise = (async () => {
|
|
46
|
+
if (config.sessionId) {
|
|
47
|
+
const loaded = await loadSessionState(config.sessionId, null);
|
|
48
|
+
if (loaded) {
|
|
49
|
+
if (config.cwd) loaded.cwd = config.cwd;
|
|
50
|
+
loaded.activeModel = config.model;
|
|
51
|
+
loaded.language = config.language;
|
|
52
|
+
loaded.autoApprove = config.autoApprove;
|
|
53
|
+
if (config.personaPrompt) loaded.personaPrompt = config.personaPrompt;
|
|
54
|
+
state = loaded;
|
|
55
|
+
return state;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (config.resume) {
|
|
59
|
+
const loaded = await loadOrCreateSessionState(null, { forceNew: false, resume: true });
|
|
60
|
+
state = loaded.state;
|
|
61
|
+
return state;
|
|
62
|
+
}
|
|
63
|
+
state = await createNewSessionState(null);
|
|
64
|
+
state.cwd = config.cwd;
|
|
65
|
+
state.activeModel = config.model;
|
|
66
|
+
state.language = config.language;
|
|
67
|
+
state.autoApprove = config.autoApprove;
|
|
68
|
+
state.personaPrompt = config.personaPrompt;
|
|
69
|
+
await saveState(state);
|
|
70
|
+
return state;
|
|
71
|
+
})();
|
|
72
|
+
}
|
|
73
|
+
return initPromise;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
emitter.send = async function send(userId, text) {
|
|
77
|
+
const s = await ensureState();
|
|
78
|
+
const userKey = userId || config.userId;
|
|
79
|
+
s.history.push({ role: 'user', content: String(text), userId: userKey });
|
|
80
|
+
const ui = noopUi();
|
|
81
|
+
const controller = new AbortController();
|
|
82
|
+
emitter.emit('turnStart', { userId: userKey, text });
|
|
83
|
+
try {
|
|
84
|
+
const result = await runAgentTurn(String(text), s, ui, { signal: controller.signal });
|
|
85
|
+
emitter.emit('turnEnd', { userId: userKey, text, content: result.content });
|
|
86
|
+
emitter.emit('message', { userId: userKey, role: 'assistant', content: result.content });
|
|
87
|
+
return result.content;
|
|
88
|
+
} catch (err) {
|
|
89
|
+
emitter.emit('error', err);
|
|
90
|
+
throw err;
|
|
91
|
+
} finally {
|
|
92
|
+
await saveState(s);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
emitter.detach = function detach(userId, text) {
|
|
97
|
+
return (async () => {
|
|
98
|
+
const s = await ensureState();
|
|
99
|
+
const userKey = userId || config.userId;
|
|
100
|
+
const taskId = enqueueBackgroundTask({ sessionId: s.sessionId, input: String(text), detachedAt: new Date().toISOString() });
|
|
101
|
+
detachBackgroundTurn({
|
|
102
|
+
taskId,
|
|
103
|
+
sessionId: s.sessionId,
|
|
104
|
+
input: String(text),
|
|
105
|
+
cwd: s.cwd,
|
|
106
|
+
modelKey: s.activeModel,
|
|
107
|
+
language: s.language,
|
|
108
|
+
personaPrompt: s.personaPrompt,
|
|
109
|
+
autoApprove: s.autoApprove,
|
|
110
|
+
});
|
|
111
|
+
return taskId;
|
|
112
|
+
})();
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
emitter.consumeBackground = async function consumeBackground() {
|
|
116
|
+
const s = await ensureState();
|
|
117
|
+
const results = await listBackgroundResults(s.sessionId);
|
|
118
|
+
for (const r of results) {
|
|
119
|
+
emitter.emit('background', r);
|
|
120
|
+
await consumeBackgroundResult(r.taskId);
|
|
121
|
+
}
|
|
122
|
+
return results;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
emitter.getState = async function getState() {
|
|
126
|
+
const s = await ensureState();
|
|
127
|
+
return {
|
|
128
|
+
sessionId: s.sessionId,
|
|
129
|
+
title: s.title,
|
|
130
|
+
cwd: s.cwd,
|
|
131
|
+
activeModel: s.activeModel,
|
|
132
|
+
language: s.language,
|
|
133
|
+
turnCount: s.turnCount,
|
|
134
|
+
historyLength: s.history.length,
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
emitter.reset = async function reset() {
|
|
139
|
+
const s = await ensureState();
|
|
140
|
+
s.history = [];
|
|
141
|
+
s.actionLog = [];
|
|
142
|
+
s.turnCount = 0;
|
|
143
|
+
s.memorySummary = '';
|
|
144
|
+
await saveState(s);
|
|
145
|
+
return true;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
emitter.close = async function close() {
|
|
149
|
+
if (state) {
|
|
150
|
+
await saveState(state);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
return emitter;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = {
|
|
158
|
+
createAgent,
|
|
159
|
+
listSkills,
|
|
160
|
+
listModels,
|
|
161
|
+
listSessions,
|
|
162
|
+
loadSessionState,
|
|
163
|
+
runBackgroundWorker,
|
|
164
|
+
runAgentTurn,
|
|
165
|
+
DEFAULT_LANGUAGE,
|
|
166
|
+
DEFAULT_MODEL_KEY,
|
|
167
|
+
MODELS,
|
|
168
|
+
};
|