zyn-ai 1.3.6 → 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 -89
- package/package.json +22 -12
- package/src/agent.js +168 -0
- package/src/cli/commands.js +461 -120
- 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 +129 -369
- package/src/core/prompts.js +181 -127
- package/src/core/skills.js +130 -31
- 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 +242 -61
- 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 +115 -317
- package/src/providers/huggingface/index.js +149 -0
- package/src/providers/qwen/index.js +0 -3
- package/src/providers/qwenapi/index.js +132 -0
- package/src/providers/scraperClient.js +27 -10
- package/src/providers/zen/index.js +84 -59
- package/src/public/helpers.js +25 -0
- package/src/tools/index.js +301 -146
- package/src/tui/app.mjs +962 -211
- package/src/utils/backgroundWorker.js +116 -0
- package/src/utils/sessionStorage.js +92 -7
- package/src/web/public/assets/index.css +1 -0
- package/src/web/public/assets/index.js +151 -0
- package/src/web/public/index.html +16 -1054
- package/src/web/server.js +62 -3
- package/src/web/store.js +23 -0
- package/src/web/webAgent.js +2 -2
package/README.md
CHANGED
|
@@ -8,42 +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
|
+
## Features
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
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
|
|
34
35
|
|
|
35
36
|
---
|
|
36
37
|
|
|
37
38
|
## Installation
|
|
38
39
|
|
|
39
|
-
### Global install
|
|
40
|
-
|
|
41
40
|
```bash
|
|
42
41
|
npm install -g zyn-ai
|
|
43
42
|
zyn
|
|
44
43
|
```
|
|
45
44
|
|
|
46
|
-
###
|
|
45
|
+
### From source
|
|
47
46
|
|
|
48
47
|
```bash
|
|
49
48
|
git clone https://github.com/SoyMaycol/Zyn.git
|
|
@@ -52,125 +51,190 @@ npm install
|
|
|
52
51
|
npm start
|
|
53
52
|
```
|
|
54
53
|
|
|
55
|
-
---
|
|
56
|
-
|
|
57
54
|
## Usage
|
|
58
55
|
|
|
59
56
|
```bash
|
|
60
|
-
zyn
|
|
61
|
-
zyn "
|
|
62
|
-
zyn --new
|
|
63
|
-
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)
|
|
64
61
|
```
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
## Web mode
|
|
69
|
-
|
|
70
|
-
Inside Zyn:
|
|
63
|
+
## Models
|
|
71
64
|
|
|
72
|
-
|
|
73
|
-
/web
|
|
74
|
-
/web 0.0.0.0:3000
|
|
75
|
-
```
|
|
65
|
+
14 built-in models across 4 providers. Each model has its real context length in the StatusBar (e.g. `10.8K/128K`).
|
|
76
66
|
|
|
77
|
-
|
|
67
|
+
### Zen (free, no configuration)
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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 |
|
|
82
75
|
|
|
83
|
-
|
|
76
|
+
### Gemini (requires API key)
|
|
84
77
|
|
|
85
|
-
|
|
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 |
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
### Qwen (requires DashScope API key)
|
|
88
88
|
|
|
89
|
-
|
|
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
|
-
|
|
95
|
+
### HuggingFace (requires HF token)
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
/lang es
|
|
98
|
-
```
|
|
97
|
+
| Key | Model | Context |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `hf-ling-2.6-1t` | InclusionAI Ling 2.6 1T | 128K |
|
|
99
100
|
|
|
100
|
-
|
|
101
|
+
Default model: `nemotron` (Zen, no configuration required).
|
|
101
102
|
|
|
102
|
-
##
|
|
103
|
+
## Commands
|
|
103
104
|
|
|
104
105
|
### Sessions
|
|
105
106
|
|
|
106
107
|
| Command | Description |
|
|
107
108
|
|---|---|
|
|
108
|
-
| `/help` | Show
|
|
109
|
-
| `/status` |
|
|
110
|
-
| `/history` |
|
|
111
|
-
| `/memory` |
|
|
112
|
-
| `/
|
|
113
|
-
| `/
|
|
114
|
-
| `/
|
|
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) |
|
|
115
117
|
| `/title <text>` | Rename session |
|
|
116
118
|
|
|
117
119
|
### Configuration
|
|
118
120
|
|
|
119
121
|
| Command | Description |
|
|
120
122
|
|---|---|
|
|
121
|
-
| `/
|
|
122
|
-
| `/
|
|
123
|
-
| `/
|
|
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 |
|
|
124
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 |
|
|
125
133
|
| `/config show` | Show config |
|
|
126
|
-
| `/
|
|
134
|
+
| `/git set\|list\|remove` | Manage git credentials |
|
|
127
135
|
| `/cwd <path>` | Change working directory |
|
|
128
136
|
|
|
129
|
-
### Tools
|
|
137
|
+
### Tools & Skills
|
|
130
138
|
|
|
131
139
|
| Command | Description |
|
|
132
140
|
|---|---|
|
|
133
|
-
| `/tools` | List tools |
|
|
134
|
-
| `/skills` | List skills |
|
|
135
|
-
| `/gmail connect` | Connect Gmail
|
|
136
|
-
| `/gmail status` | Show Gmail connection status |
|
|
137
|
-
| `/gmail disconnect` | Remove saved Gmail tokens |
|
|
138
|
-
| `/cwd` | Show working directory |
|
|
141
|
+
| `/tools` | List agent tools |
|
|
142
|
+
| `/skills` | List loaded skills |
|
|
143
|
+
| `/gmail connect` | Connect Gmail via OAuth |
|
|
139
144
|
|
|
140
|
-
###
|
|
145
|
+
### Export & Control
|
|
141
146
|
|
|
142
147
|
| Command | Description |
|
|
143
148
|
|---|---|
|
|
144
|
-
| `/
|
|
145
|
-
| `/transcript` |
|
|
146
|
-
| `/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 |
|
|
147
157
|
|
|
148
|
-
|
|
158
|
+
Press `ESC` twice in the TUI to stop the current task.
|
|
149
159
|
|
|
150
|
-
|
|
151
|
-
|---|---|
|
|
152
|
-
| `/stop` | Stop current task |
|
|
153
|
-
| `/reset` | Reset session |
|
|
154
|
-
| `/exit` | Exit Zyn |
|
|
160
|
+
## Custom Providers
|
|
155
161
|
|
|
156
|
-
|
|
162
|
+
Add any OpenAI-compatible API:
|
|
157
163
|
|
|
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`.
|
|
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
|
|
158
183
|
---
|
|
159
184
|
|
|
160
|
-
|
|
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
|
|
161
191
|
|
|
162
|
-
|
|
192
|
+
### Embed in your bot
|
|
163
193
|
|
|
164
|
-
|
|
194
|
+
```js
|
|
195
|
+
const { createAgent } = require('zyn-ai');
|
|
165
196
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
197
|
+
const agent = createAgent({
|
|
198
|
+
model: 'nemotron',
|
|
199
|
+
language: 'en',
|
|
200
|
+
autoApprove: false,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const response = await agent.send('userId', 'Hello!');
|
|
176
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,23 +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
|
-
"keypress": "^0.2.1",
|
|
39
40
|
"react": "^19.0.0",
|
|
40
|
-
"
|
|
41
|
-
|
|
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"
|
|
42
47
|
},
|
|
43
48
|
"repository": {
|
|
44
49
|
"type": "git",
|
|
@@ -59,7 +64,12 @@
|
|
|
59
64
|
"LICENSE"
|
|
60
65
|
],
|
|
61
66
|
"exports": {
|
|
62
|
-
".": "./
|
|
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"
|
|
63
73
|
},
|
|
64
74
|
"preferGlobal": true
|
|
65
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
|
+
};
|