zeta-assistant 0.1.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 +238 -0
- package/dist/agent/agent-loop.d.ts +7 -0
- package/dist/agent/agent-loop.d.ts.map +1 -0
- package/dist/agent/agent-loop.js +34 -0
- package/dist/agent/agent-loop.js.map +1 -0
- package/dist/agent/index.d.ts +2 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +2 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/planner.d.ts +8 -0
- package/dist/agent/planner.d.ts.map +1 -0
- package/dist/agent/planner.js +87 -0
- package/dist/agent/planner.js.map +1 -0
- package/dist/config/config-loader.d.ts +5 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +27 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/executor/command-executor.d.ts +7 -0
- package/dist/executor/command-executor.d.ts.map +1 -0
- package/dist/executor/command-executor.js +34 -0
- package/dist/executor/command-executor.js.map +1 -0
- package/dist/executor/index.d.ts +2 -0
- package/dist/executor/index.d.ts.map +1 -0
- package/dist/executor/index.js +2 -0
- package/dist/executor/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/index.d.ts +3 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +2 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/logger.d.ts +8 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.js +2 -0
- package/dist/logger/logger.js.map +1 -0
- package/dist/logger/winston-logger.d.ts +19 -0
- package/dist/logger/winston-logger.d.ts.map +1 -0
- package/dist/logger/winston-logger.js +65 -0
- package/dist/logger/winston-logger.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +67 -0
- package/dist/main.js.map +1 -0
- package/dist/types/index.d.ts +24 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/cli-parser.d.ts +4 -0
- package/dist/utils/cli-parser.d.ts.map +1 -0
- package/dist/utils/cli-parser.js +34 -0
- package/dist/utils/cli-parser.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/whatsapp/index.d.ts +3 -0
- package/dist/whatsapp/index.d.ts.map +1 -0
- package/dist/whatsapp/index.js +2 -0
- package/dist/whatsapp/index.js.map +1 -0
- package/dist/whatsapp/whatsapp-client.d.ts +25 -0
- package/dist/whatsapp/whatsapp-client.d.ts.map +1 -0
- package/dist/whatsapp/whatsapp-client.js +150 -0
- package/dist/whatsapp/whatsapp-client.js.map +1 -0
- package/package.json +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Zeta Assistant
|
|
2
|
+
|
|
3
|
+
A locally running AI operator controlled via WhatsApp Web. Send a message from your phone and Zeta plans, validates, and executes tasks autonomously — all from your terminal.
|
|
4
|
+
|
|
5
|
+
> **Status:** Phase 2 complete — AI agent loop with o3-mini, command execution, and WhatsApp replies working.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## How It Works
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
You (WhatsApp) → Message → Zeta (terminal) → o3-mini plans commands → Executes on your machine → Replies on WhatsApp
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
1. Run `OPEN_AI_API_KEY=sk-... npx zeta-assistant` in your terminal
|
|
16
|
+
2. Scan the QR code with WhatsApp on your phone
|
|
17
|
+
3. Send yourself a message (to your own number) — Zeta picks it up
|
|
18
|
+
4. The AI planner (o3-mini) decides what shell commands to run
|
|
19
|
+
5. Commands execute in parallel on your machine
|
|
20
|
+
6. Zeta summarises the results and replies on WhatsApp
|
|
21
|
+
|
|
22
|
+
The assistant runs **only while the terminal is open**. No cloud, no webhooks, no public exposure. Only messages you send to yourself are processed — messages from others are ignored.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Prerequisites
|
|
27
|
+
|
|
28
|
+
- **Node.js** >= 20.0.0
|
|
29
|
+
- A **WhatsApp** account
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### Option 1: npx (recommended)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
OPEN_AI_API_KEY=sk-... npx zeta-assistant
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or with the flag:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx zeta-assistant --OPEN_AI_API_KEY=sk-...
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Option 2: Clone and run with npm
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# 1. Clone the repository
|
|
51
|
+
git clone https://github.com/your-org/zeta-assistant.git
|
|
52
|
+
cd zeta-assistant
|
|
53
|
+
|
|
54
|
+
# 2. Install dependencies
|
|
55
|
+
npm install
|
|
56
|
+
|
|
57
|
+
# 3. Build
|
|
58
|
+
npm run build
|
|
59
|
+
|
|
60
|
+
# 4. Run
|
|
61
|
+
OPEN_AI_API_KEY=sk-... npm start
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
On first run, a **QR code** appears in the terminal. Scan it with WhatsApp on your phone. The session is persisted in `~/.zeta/whatsapp-session/` so you only need to scan once.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Dedicated Browser
|
|
69
|
+
|
|
70
|
+
Zeta downloads and manages its **own Chromium instance** — completely separate from your personal browser. This is the "Zeta browser".
|
|
71
|
+
|
|
72
|
+
**Why?** This is both a feature and a security model:
|
|
73
|
+
|
|
74
|
+
- **You control what Zeta can access.** Log into sites (Instagram, Twitter, Gmail, etc.) inside the Zeta browser and the assistant can operate them on your behalf.
|
|
75
|
+
- **Your personal browser is never touched.** Zeta has zero access to your personal cookies, sessions, or passwords.
|
|
76
|
+
- **Sites you don't log into are inaccessible.** Zeta can only control what you explicitly grant.
|
|
77
|
+
|
|
78
|
+
The Chromium binary is downloaded automatically during `npm install` via Puppeteer.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## CLI Usage
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
zeta-assistant [options]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
| Flag | Description |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `--OPEN_AI_API_KEY=<key>` | OpenAI API key **(required)**. Also reads `OPEN_AI_API_KEY` env var. |
|
|
91
|
+
| `--reset-whatsapp` | Clear saved session and force a new QR code scan |
|
|
92
|
+
| `--help`, `-h` | Show help message |
|
|
93
|
+
| `--version`, `-v` | Show version number |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Tech Stack
|
|
98
|
+
|
|
99
|
+
### Current (Phase 1–2)
|
|
100
|
+
|
|
101
|
+
| Category | Technology | Purpose |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| **Language** | [TypeScript](https://www.typescriptlang.org/) 5.x | Strict mode, no `any`, fully typed |
|
|
104
|
+
| **Runtime** | [Node.js](https://nodejs.org/) >= 20 | ESM, modern APIs |
|
|
105
|
+
| **AI** | [OpenAI o3-mini](https://platform.openai.com/) | Planner — batches shell commands from natural language |
|
|
106
|
+
| **WhatsApp** | [whatsapp-web.js](https://github.com/pedroslopez/whatsapp-web.js) | WhatsApp Web client via Puppeteer |
|
|
107
|
+
| **Browser** | Chromium (via Puppeteer) | Dedicated browser instance, isolated from personal browser |
|
|
108
|
+
| **QR Display** | [qrcode-terminal](https://www.npmjs.com/package/qrcode-terminal) | QR code rendered in the terminal |
|
|
109
|
+
| **Logging** | [Winston](https://github.com/winstonjs/winston) | Colored console to stderr + JSON lines to file |
|
|
110
|
+
| **Testing** | [Jest](https://jestjs.io/) + [ts-jest](https://kulshekhar.github.io/ts-jest/) | Unit tests, ESM mode, 80%+ coverage |
|
|
111
|
+
| **Linting** | [ESLint](https://eslint.org/) + [@typescript-eslint](https://typescript-eslint.io/) | Strict type-checked rules |
|
|
112
|
+
| **Formatting** | [Prettier](https://prettier.io/) | Consistent code style |
|
|
113
|
+
| **Git Hooks** | [Husky](https://typicode.github.io/husky/) + [lint-staged](https://github.com/lint-staged/lint-staged) | Pre-commit lint + format |
|
|
114
|
+
|
|
115
|
+
### Planned (Upcoming Phases)
|
|
116
|
+
|
|
117
|
+
| Category | Technology | Phase | Purpose |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| **Database** | [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) | 4 | Task queue, session messages (SQLite) |
|
|
120
|
+
| **Screenshot** | [Puppeteer](https://pptr.dev/) (direct) | 3 | `take_screenshot` tool |
|
|
121
|
+
|
|
122
|
+
### Intentionally Not Used
|
|
123
|
+
|
|
124
|
+
| Technology | Reason |
|
|
125
|
+
|---|---|
|
|
126
|
+
| Twilio / ngrok | No cloud dependency. WhatsApp Web only. |
|
|
127
|
+
| Express / Fastify | No HTTP server. No webhooks. |
|
|
128
|
+
| Commander / yargs | Minimal deps. Raw `process.argv` for 3 flags. |
|
|
129
|
+
| dotenv | No `.env` files. API key passed via CLI flag or env var directly. |
|
|
130
|
+
| Prisma / TypeORM | `better-sqlite3` is simpler for a single-file embedded database. |
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Project Structure
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
zeta-assistant/
|
|
138
|
+
├── src/
|
|
139
|
+
│ ├── main.ts # CLI entry point (shebang, arg parsing, shutdown)
|
|
140
|
+
│ ├── index.ts # Library entry point (public API exports)
|
|
141
|
+
│ ├── agent/
|
|
142
|
+
│ │ ├── agent-loop.ts # Orchestrates: message → plan → execute → reply
|
|
143
|
+
│ │ └── planner.ts # o3-mini planner (batches shell commands)
|
|
144
|
+
│ ├── executor/
|
|
145
|
+
│ │ └── command-executor.ts # Parallel shell command execution (/bin/bash)
|
|
146
|
+
│ ├── config/
|
|
147
|
+
│ │ └── config-loader.ts # Directory setup (~/.zeta)
|
|
148
|
+
│ ├── whatsapp/
|
|
149
|
+
│ │ └── whatsapp-client.ts # whatsapp-web.js wrapper
|
|
150
|
+
│ ├── logger/
|
|
151
|
+
│ │ ├── logger.ts # Logger interface (swap implementations easily)
|
|
152
|
+
│ │ └── winston-logger.ts # Winston impl: colored stderr + JSON lines to file
|
|
153
|
+
│ ├── types/
|
|
154
|
+
│ │ ├── index.ts # Shared interfaces (ZetaConfig, CliArgs, PlannerOutput)
|
|
155
|
+
│ │ └── qrcode-terminal.d.ts # Type declarations for untyped package
|
|
156
|
+
│ └── utils/
|
|
157
|
+
│ └── cli-parser.ts # Minimal process.argv parser
|
|
158
|
+
├── tests/
|
|
159
|
+
│ └── unit/ # Mirrors src/ structure
|
|
160
|
+
├── docs/
|
|
161
|
+
│ └── prd.md # Product requirements & technical spec
|
|
162
|
+
├── package.json
|
|
163
|
+
├── tsconfig.json
|
|
164
|
+
├── tsconfig.build.json
|
|
165
|
+
├── tsconfig.test.json
|
|
166
|
+
├── jest.config.ts
|
|
167
|
+
├── eslint.config.js
|
|
168
|
+
├── .prettierrc
|
|
169
|
+
└── CONTRIBUTING.md # Coding standards & best practices
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Runtime Data (`~/.zeta/`)
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
~/.zeta/
|
|
176
|
+
├── whatsapp-session/ # Persisted WhatsApp login (LocalAuth)
|
|
177
|
+
├── logs/
|
|
178
|
+
│ └── zeta.log # JSON lines log file (Winston file transport)
|
|
179
|
+
├── scripts/ # Reusable scripts (Phase 7)
|
|
180
|
+
├── sessions.db # SQLite task queue (Phase 4)
|
|
181
|
+
└── global_context.json # Cross-task memory (Phase 9)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Development
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Install dependencies
|
|
190
|
+
npm install
|
|
191
|
+
|
|
192
|
+
# Type check
|
|
193
|
+
npm run typecheck
|
|
194
|
+
|
|
195
|
+
# Build
|
|
196
|
+
npm run build
|
|
197
|
+
|
|
198
|
+
# Run tests
|
|
199
|
+
npm test
|
|
200
|
+
|
|
201
|
+
# Run tests with coverage report
|
|
202
|
+
npm run test:coverage
|
|
203
|
+
|
|
204
|
+
# Lint
|
|
205
|
+
npm run lint
|
|
206
|
+
|
|
207
|
+
# Format
|
|
208
|
+
npm run format
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Roadmap
|
|
214
|
+
|
|
215
|
+
| Phase | Goal | Status |
|
|
216
|
+
|---|---|---|
|
|
217
|
+
| 1 | WhatsApp connection, QR login, message reception | ✅ Done |
|
|
218
|
+
| 2 | AI agent loop (o3-mini), command execution, reply to messages | ✅ Done |
|
|
219
|
+
| 3 | Screenshot tool, media attachments | ⬜ |
|
|
220
|
+
| 4 | SQLite task queue, FIFO processing | ⬜ |
|
|
221
|
+
| 5 | Governor + Decision Engine, confirmation flow | ⬜ |
|
|
222
|
+
| 6 | Script registry (create, reuse, update) | ⬜ |
|
|
223
|
+
| 7 | Full JSONL structured logging | ⬜ |
|
|
224
|
+
| 8 | Global context persistence | ⬜ |
|
|
225
|
+
|
|
226
|
+
> Full product requirements and technical specification: [`docs/prd.md`](docs/prd.md)
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Contributing
|
|
231
|
+
|
|
232
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for coding standards, naming conventions, testing requirements, and best practices.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## License
|
|
237
|
+
|
|
238
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../../src/agent/agent-loop.ts"],"names":[],"mappings":"AAOA,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;gBAEtC,MAAM,EAAE,MAAM;IAIpB,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAkBhD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Planner } from './planner.js';
|
|
2
|
+
import { CommandExecutor } from '../executor/index.js';
|
|
3
|
+
import { WinstonLogger } from '../logger/index.js';
|
|
4
|
+
const logger = new WinstonLogger('AgentLoop');
|
|
5
|
+
export class AgentLoop {
|
|
6
|
+
planner;
|
|
7
|
+
executor = new CommandExecutor();
|
|
8
|
+
constructor(apiKey) {
|
|
9
|
+
this.planner = new Planner(apiKey);
|
|
10
|
+
}
|
|
11
|
+
async run(userMessage) {
|
|
12
|
+
logger.info(`Running agent loop for: "${userMessage}"`);
|
|
13
|
+
const plan = await this.planner.plan(userMessage);
|
|
14
|
+
logger.info(`Reasoning: ${plan.reasoning}`);
|
|
15
|
+
if (plan.commands.length === 0) {
|
|
16
|
+
return plan.reply || 'Done.';
|
|
17
|
+
}
|
|
18
|
+
logger.info(`Executing ${String(plan.commands.length)} command(s) in parallel...`);
|
|
19
|
+
const results = await this.executor.run(plan.commands);
|
|
20
|
+
const commandResults = formatCommandResults(results);
|
|
21
|
+
logger.info(`Command results:\n${commandResults}`);
|
|
22
|
+
return this.planner.summarise(userMessage, commandResults);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function formatCommandResults(results) {
|
|
26
|
+
return results
|
|
27
|
+
.map((r) => {
|
|
28
|
+
const status = r.exitCode === 0 ? '✓' : '✗';
|
|
29
|
+
const output = r.stdout || r.stderr || '(no output)';
|
|
30
|
+
return `${status} ${r.command}\n${output}`;
|
|
31
|
+
})
|
|
32
|
+
.join('\n\n');
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=agent-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loop.js","sourceRoot":"","sources":["../../src/agent/agent-loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;AAE9C,MAAM,OAAO,SAAS;IACH,OAAO,CAAU;IACjB,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IAElD,YAAY,MAAc;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,WAAmB;QAC3B,MAAM,CAAC,IAAI,CAAC,4BAA4B,WAAW,GAAG,CAAC,CAAC;QAExD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAE5C,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC;QAC/B,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEvD,MAAM,cAAc,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,CAAC,IAAI,CAAC,qBAAqB,cAAc,EAAE,CAAC,CAAC;QAEnD,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC7D,CAAC;CACF;AAED,SAAS,oBAAoB,CAAC,OAAiC;IAC7D,OAAO,OAAO;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC5C,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,IAAI,aAAa,CAAC;QACrD,OAAO,GAAG,MAAM,IAAI,CAAC,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;IAC7C,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PlannerOutput } from '../types/index.js';
|
|
2
|
+
export declare class Planner {
|
|
3
|
+
private readonly client;
|
|
4
|
+
constructor(apiKey: string);
|
|
5
|
+
plan(userMessage: string): Promise<PlannerOutput>;
|
|
6
|
+
summarise(userMessage: string, commandResults: string): Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=planner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../src/agent/planner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAsCvD,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,EAAE,MAAM;IAIpB,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAkBjD,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAiB9E"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { platform, arch } from 'node:process';
|
|
3
|
+
import OpenAI from 'openai';
|
|
4
|
+
import { WinstonLogger } from '../logger/index.js';
|
|
5
|
+
// o3-mini is the best reasoning/planning model — ideal for batching multi-step actions.
|
|
6
|
+
const PLANNER_MODEL = 'o3-mini';
|
|
7
|
+
function buildSystemPrompt() {
|
|
8
|
+
return `You are Zeta, an AI assistant that controls a computer via shell commands.
|
|
9
|
+
|
|
10
|
+
Environment:
|
|
11
|
+
- OS: ${platform} (${arch})
|
|
12
|
+
- Shell: /bin/bash
|
|
13
|
+
- Home directory: ${homedir()}
|
|
14
|
+
- Working directory: ${homedir()}
|
|
15
|
+
|
|
16
|
+
When the user sends a request, you must:
|
|
17
|
+
1. Determine ALL commands needed to answer the request in ONE response.
|
|
18
|
+
2. Batch all necessary commands together. Prefer fewer, broader commands over many narrow ones.
|
|
19
|
+
3. Return a JSON object with this exact shape:
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
"commands": ["cmd1", "cmd2"],
|
|
23
|
+
"reasoning": "why these commands answer the request",
|
|
24
|
+
"reply": ""
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
If no commands are needed (e.g. a greeting or simple question), return an empty commands array and put the answer directly in reply.
|
|
28
|
+
|
|
29
|
+
Rules:
|
|
30
|
+
- All commands run in /bin/bash from the home directory.
|
|
31
|
+
- Use absolute paths or cd into directories explicitly.
|
|
32
|
+
- Always prefer read-only commands unless the user explicitly asks to change something.
|
|
33
|
+
- Never use sudo unless explicitly requested.
|
|
34
|
+
- Do NOT have conversations. You are a task executor, not a chatbot. If the message is just a greeting or casual chat, reply briefly and do not ask follow-up questions.
|
|
35
|
+
- The "reply" field is filled AFTER command results are observed. Leave it empty when commands are present.`;
|
|
36
|
+
}
|
|
37
|
+
const logger = new WinstonLogger('Planner');
|
|
38
|
+
export class Planner {
|
|
39
|
+
client;
|
|
40
|
+
constructor(apiKey) {
|
|
41
|
+
this.client = new OpenAI({ apiKey });
|
|
42
|
+
}
|
|
43
|
+
async plan(userMessage) {
|
|
44
|
+
logger.info(`Planning for: ${userMessage}`);
|
|
45
|
+
const response = await this.client.chat.completions.create({
|
|
46
|
+
model: PLANNER_MODEL,
|
|
47
|
+
response_format: { type: 'json_object' },
|
|
48
|
+
messages: [
|
|
49
|
+
{ role: 'system', content: buildSystemPrompt() },
|
|
50
|
+
{ role: 'user', content: userMessage },
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
const raw = response.choices[0]?.message?.content ?? '{}';
|
|
54
|
+
logger.info(`Planner raw response: ${raw}`);
|
|
55
|
+
return parsePlannerOutput(raw);
|
|
56
|
+
}
|
|
57
|
+
async summarise(userMessage, commandResults) {
|
|
58
|
+
logger.info('Summarising command results...');
|
|
59
|
+
const response = await this.client.chat.completions.create({
|
|
60
|
+
model: PLANNER_MODEL,
|
|
61
|
+
messages: [
|
|
62
|
+
{ role: 'system', content: buildSystemPrompt() },
|
|
63
|
+
{ role: 'user', content: userMessage },
|
|
64
|
+
{
|
|
65
|
+
role: 'user',
|
|
66
|
+
content: `Command results:\n${commandResults}\n\nNow write the final reply to the user based on these results. Be concise and direct.`,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
return response.choices[0]?.message?.content?.trim() ?? 'Done.';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function parsePlannerOutput(raw) {
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(raw);
|
|
76
|
+
return {
|
|
77
|
+
commands: Array.isArray(parsed.commands) ? parsed.commands : [],
|
|
78
|
+
reasoning: typeof parsed.reasoning === 'string' ? parsed.reasoning : '',
|
|
79
|
+
reply: typeof parsed.reply === 'string' ? parsed.reply : '',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
logger.warn(`Failed to parse planner output, treating as plain reply: ${raw}`);
|
|
84
|
+
return { commands: [], reasoning: '', reply: raw };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=planner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../src/agent/planner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ZetaConfig } from '../types/index.js';
|
|
2
|
+
export declare function ensureDirectory(dirPath: string): void;
|
|
3
|
+
export declare function ensureZetaDirectories(zetaDir: string): void;
|
|
4
|
+
export declare function initConfig(): ZetaConfig;
|
|
5
|
+
//# sourceMappingURL=config-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/config/config-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAKpD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAIrD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAK3D;AAED,wBAAgB,UAAU,IAAI,UAAU,CAWvC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { mkdirSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
const DEFAULT_ZETA_DIR = join(homedir(), '.zeta');
|
|
5
|
+
const REQUIRED_SUBDIRS = ['whatsapp-session', 'logs', 'scripts'];
|
|
6
|
+
export function ensureDirectory(dirPath) {
|
|
7
|
+
if (!existsSync(dirPath)) {
|
|
8
|
+
mkdirSync(dirPath, { recursive: true });
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function ensureZetaDirectories(zetaDir) {
|
|
12
|
+
ensureDirectory(zetaDir);
|
|
13
|
+
for (const subdir of REQUIRED_SUBDIRS) {
|
|
14
|
+
ensureDirectory(join(zetaDir, subdir));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function initConfig() {
|
|
18
|
+
const zetaDir = DEFAULT_ZETA_DIR;
|
|
19
|
+
ensureZetaDirectories(zetaDir);
|
|
20
|
+
return {
|
|
21
|
+
zetaDir,
|
|
22
|
+
whatsappSessionPath: join(zetaDir, 'whatsapp-session'),
|
|
23
|
+
logsDir: join(zetaDir, 'logs'),
|
|
24
|
+
scriptsDir: join(zetaDir, 'scripts'),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=config-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/config/config-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AAClD,MAAM,gBAAgB,GAAG,CAAC,kBAAkB,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;AAE1E,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,eAAe,CAAC,OAAO,CAAC,CAAC;IACzB,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACtC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,OAAO,GAAG,gBAAgB,CAAC;IAEjC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAE/B,OAAO;QACL,OAAO;QACP,mBAAmB,EAAE,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC;QACtD,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;QAC9B,UAAU,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;KACrC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-executor.d.ts","sourceRoot":"","sources":["../../src/executor/command-executor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAKvD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;IAE5D,GAAG,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;YAIlD,MAAM;CAuBrB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { exec } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { WinstonLogger } from '../logger/index.js';
|
|
5
|
+
const execAsync = promisify(exec);
|
|
6
|
+
const COMMAND_TIMEOUT_MS = 30_000;
|
|
7
|
+
export class CommandExecutor {
|
|
8
|
+
logger = new WinstonLogger(CommandExecutor.name);
|
|
9
|
+
async run(commands) {
|
|
10
|
+
return Promise.all(commands.map((cmd) => this.runOne(cmd)));
|
|
11
|
+
}
|
|
12
|
+
async runOne(command) {
|
|
13
|
+
this.logger.warn(`Executing command: ${command}`);
|
|
14
|
+
try {
|
|
15
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
16
|
+
timeout: COMMAND_TIMEOUT_MS,
|
|
17
|
+
encoding: 'utf-8',
|
|
18
|
+
shell: '/bin/bash',
|
|
19
|
+
cwd: homedir(),
|
|
20
|
+
});
|
|
21
|
+
return { command, stdout: stdout.trim(), stderr: stderr.trim(), exitCode: 0 };
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
const err = error;
|
|
25
|
+
return {
|
|
26
|
+
command,
|
|
27
|
+
stdout: err.stdout?.trim() ?? '',
|
|
28
|
+
stderr: err.stderr?.trim() ?? err.message ?? 'Unknown error',
|
|
29
|
+
exitCode: err.code ?? 1,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=command-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-executor.js","sourceRoot":"","sources":["../../src/executor/command-executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAClC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,MAAM,OAAO,eAAe;IACT,MAAM,GAAG,IAAI,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAElE,KAAK,CAAC,GAAG,CAAC,QAA2B;QACnC,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,OAAe;QAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,OAAO,EAAE,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE;gBAClD,OAAO,EAAE,kBAAkB;gBAC3B,QAAQ,EAAE,OAAO;gBACjB,KAAK,EAAE,WAAW;gBAClB,GAAG,EAAE,OAAO,EAAE;aACf,CAAC,CAAC;YAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QAChF,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,KAA8E,CAAC;YAE3F,OAAO;gBACL,OAAO;gBACP,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE;gBAChC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,OAAO,IAAI,eAAe;gBAC5D,QAAQ,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC;aACxB,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/executor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/executor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { initConfig } from './config/index.js';
|
|
2
|
+
export { WhatsappClient, initWhatsapp } from './whatsapp/index.js';
|
|
3
|
+
export { WinstonLogger, initLoggerTransports } from './logger/index.js';
|
|
4
|
+
export type { Logger, LogLevel } from './logger/index.js';
|
|
5
|
+
export type { ZetaConfig, CliArgs } from './types/index.js';
|
|
6
|
+
export type { WhatsappClientOptions, MessageHandler } from './whatsapp/index.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logger/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logger/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logger/logger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger/logger.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Logger } from './logger.js';
|
|
2
|
+
export declare function initLoggerTransports(logsDir: string): void;
|
|
3
|
+
/** @internal */
|
|
4
|
+
export declare function _resetFileTransport(): void;
|
|
5
|
+
export declare function formatLogEntry(entry: {
|
|
6
|
+
level: string;
|
|
7
|
+
message: string;
|
|
8
|
+
timestamp?: string;
|
|
9
|
+
context?: string;
|
|
10
|
+
}): string;
|
|
11
|
+
export declare class WinstonLogger implements Logger {
|
|
12
|
+
private readonly context;
|
|
13
|
+
constructor(context: string);
|
|
14
|
+
info(message: string): void;
|
|
15
|
+
warn(message: string): void;
|
|
16
|
+
error(message: string): void;
|
|
17
|
+
debug(message: string): void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=winston-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"winston-logger.d.ts","sourceRoot":"","sources":["../../src/logger/winston-logger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AA+B1C,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAa1D;AAED,gBAAgB;AAChB,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAKT;AAED,qBAAa,aAAc,YAAW,MAAM;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,MAAM;IAI3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAG7B"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createLogger, format, transports } from 'winston';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const LEVEL_COLORS = {
|
|
4
|
+
info: '\x1b[36m',
|
|
5
|
+
warn: '\x1b[33m',
|
|
6
|
+
error: '\x1b[31m',
|
|
7
|
+
debug: '\x1b[90m',
|
|
8
|
+
};
|
|
9
|
+
const RESET = '\x1b[0m';
|
|
10
|
+
const consoleFormat = format.printf(({ level, message, timestamp, context }) => {
|
|
11
|
+
const color = LEVEL_COLORS[level] ?? '';
|
|
12
|
+
const tag = level.toUpperCase().padEnd(5);
|
|
13
|
+
const ctx = typeof context === 'string' ? context : 'App';
|
|
14
|
+
return `${color}[${String(timestamp)}] [${tag}] [${ctx}]${RESET} ${String(message)}`;
|
|
15
|
+
});
|
|
16
|
+
const winstonInstance = createLogger({
|
|
17
|
+
level: 'debug',
|
|
18
|
+
transports: [
|
|
19
|
+
new transports.Console({
|
|
20
|
+
stderrLevels: ['info', 'warn', 'error', 'debug'],
|
|
21
|
+
format: format.combine(format.timestamp(), consoleFormat),
|
|
22
|
+
}),
|
|
23
|
+
],
|
|
24
|
+
});
|
|
25
|
+
// Winston throws if you add the same file transport twice, so we guard with a flag.
|
|
26
|
+
let fileTransportAdded = false;
|
|
27
|
+
export function initLoggerTransports(logsDir) {
|
|
28
|
+
if (fileTransportAdded) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
winstonInstance.add(new transports.File({
|
|
32
|
+
filename: join(logsDir, 'zeta.log'),
|
|
33
|
+
format: format.combine(format.timestamp(), format.json()),
|
|
34
|
+
}));
|
|
35
|
+
fileTransportAdded = true;
|
|
36
|
+
}
|
|
37
|
+
/** @internal */
|
|
38
|
+
export function _resetFileTransport() {
|
|
39
|
+
fileTransportAdded = false;
|
|
40
|
+
}
|
|
41
|
+
export function formatLogEntry(entry) {
|
|
42
|
+
const color = LEVEL_COLORS[entry.level] ?? '';
|
|
43
|
+
const tag = entry.level.toUpperCase().padEnd(5);
|
|
44
|
+
const ctx = typeof entry.context === 'string' ? entry.context : 'App';
|
|
45
|
+
return `${color}[${String(entry.timestamp ?? new Date().toISOString())}] [${tag}] [${ctx}]${RESET} ${String(entry.message)}`;
|
|
46
|
+
}
|
|
47
|
+
export class WinstonLogger {
|
|
48
|
+
context;
|
|
49
|
+
constructor(context) {
|
|
50
|
+
this.context = context;
|
|
51
|
+
}
|
|
52
|
+
info(message) {
|
|
53
|
+
winstonInstance.info(message, { context: this.context });
|
|
54
|
+
}
|
|
55
|
+
warn(message) {
|
|
56
|
+
winstonInstance.warn(message, { context: this.context });
|
|
57
|
+
}
|
|
58
|
+
error(message) {
|
|
59
|
+
winstonInstance.error(message, { context: this.context });
|
|
60
|
+
}
|
|
61
|
+
debug(message) {
|
|
62
|
+
winstonInstance.debug(message, { context: this.context });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=winston-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"winston-logger.js","sourceRoot":"","sources":["../../src/logger/winston-logger.ts"],"names":[],"mappings":"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"}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { initConfig } from './config/index.js';
|
|
4
|
+
import { initWhatsapp } from './whatsapp/index.js';
|
|
5
|
+
import { parseCliArgs, getHelpText } from './utils/index.js';
|
|
6
|
+
import { WinstonLogger, initLoggerTransports } from './logger/index.js';
|
|
7
|
+
import { AgentLoop } from './agent/index.js';
|
|
8
|
+
const logger = new WinstonLogger('Main');
|
|
9
|
+
function getVersion() {
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const pkg = require('../package.json');
|
|
12
|
+
return pkg.version;
|
|
13
|
+
}
|
|
14
|
+
function requirePlannerApiKey(plannerApiKey) {
|
|
15
|
+
if (!plannerApiKey) {
|
|
16
|
+
logger.error('OPEN_AI_API_KEY is required. Pass it via --OPEN_AI_API_KEY=<key> or set OPEN_AI_API_KEY env var.');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
return plannerApiKey;
|
|
20
|
+
}
|
|
21
|
+
function initGracefulShutdown(whatsapp) {
|
|
22
|
+
const shutdown = async (signal) => {
|
|
23
|
+
logger.info(`Received ${signal}. Shutting down gracefully...`);
|
|
24
|
+
await whatsapp.destroy();
|
|
25
|
+
process.exit(0);
|
|
26
|
+
};
|
|
27
|
+
process.on('SIGINT', () => void shutdown('SIGINT'));
|
|
28
|
+
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
|
29
|
+
}
|
|
30
|
+
async function main() {
|
|
31
|
+
const args = parseCliArgs(process.argv);
|
|
32
|
+
if (args.help) {
|
|
33
|
+
console.error(getHelpText());
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
if (args.version) {
|
|
37
|
+
console.error(getVersion());
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
const apiKey = requirePlannerApiKey(args.plannerApiKey);
|
|
41
|
+
const agentLoop = new AgentLoop(apiKey);
|
|
42
|
+
logger.info(`Zeta Assistant v${getVersion()} starting...`);
|
|
43
|
+
const config = initConfig();
|
|
44
|
+
initLoggerTransports(config.logsDir);
|
|
45
|
+
const whatsapp = await initWhatsapp({
|
|
46
|
+
config,
|
|
47
|
+
resetSession: args.resetWhatsapp,
|
|
48
|
+
onMessage: (sender, body) => {
|
|
49
|
+
agentLoop
|
|
50
|
+
.run(body)
|
|
51
|
+
.then(async (reply) => {
|
|
52
|
+
await whatsapp.sendMessage(sender, reply);
|
|
53
|
+
})
|
|
54
|
+
.catch((error) => {
|
|
55
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56
|
+
logger.error(`Agent loop error: ${message}`);
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
initGracefulShutdown(whatsapp);
|
|
61
|
+
}
|
|
62
|
+
main().catch((error) => {
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64
|
+
logger.error(`Fatal: ${message}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface ZetaConfig {
|
|
2
|
+
readonly zetaDir: string;
|
|
3
|
+
readonly whatsappSessionPath: string;
|
|
4
|
+
readonly logsDir: string;
|
|
5
|
+
readonly scriptsDir: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CliArgs {
|
|
8
|
+
readonly resetWhatsapp: boolean;
|
|
9
|
+
readonly help: boolean;
|
|
10
|
+
readonly version: boolean;
|
|
11
|
+
readonly plannerApiKey: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface CommandResult {
|
|
14
|
+
readonly command: string;
|
|
15
|
+
readonly stdout: string;
|
|
16
|
+
readonly stderr: string;
|
|
17
|
+
readonly exitCode: number;
|
|
18
|
+
}
|
|
19
|
+
export interface PlannerOutput {
|
|
20
|
+
readonly commands: readonly string[];
|
|
21
|
+
readonly reasoning: string;
|
|
22
|
+
readonly reply: string;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-parser.d.ts","sourceRoot":"","sources":["../../src/utils/cli-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAc7D;AAED,wBAAgB,WAAW,IAAI,MAAM,CAmBpC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function parseCliArgs(argv) {
|
|
2
|
+
const args = argv.slice(2);
|
|
3
|
+
const plannerApiKeyArg = args.find((a) => a.startsWith('--OPEN_AI_API_KEY='));
|
|
4
|
+
const plannerApiKey = plannerApiKeyArg
|
|
5
|
+
? (plannerApiKeyArg.split('=')[1] ?? null)
|
|
6
|
+
: (process.env['OPEN_AI_API_KEY'] ?? null);
|
|
7
|
+
return {
|
|
8
|
+
resetWhatsapp: args.includes('--reset-whatsapp'),
|
|
9
|
+
help: args.includes('--help') || args.includes('-h'),
|
|
10
|
+
version: args.includes('--version') || args.includes('-v'),
|
|
11
|
+
plannerApiKey,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function getHelpText() {
|
|
15
|
+
return `
|
|
16
|
+
Usage: zeta-assistant [options]
|
|
17
|
+
|
|
18
|
+
A locally running AI operator controlled via WhatsApp Web.
|
|
19
|
+
|
|
20
|
+
Options:
|
|
21
|
+
--OPEN_AI_API_KEY=<key> OpenAI API key (required). Can also be set via OPEN_AI_API_KEY env var.
|
|
22
|
+
--reset-whatsapp Clear saved session and scan a new QR code
|
|
23
|
+
--help, -h Show this help message
|
|
24
|
+
--version, -v Show version number
|
|
25
|
+
|
|
26
|
+
Prerequisites:
|
|
27
|
+
- Node.js >= 20
|
|
28
|
+
|
|
29
|
+
Examples:
|
|
30
|
+
npx zeta-assistant --OPEN_AI_API_KEY=sk-...
|
|
31
|
+
OPEN_AI_API_KEY=sk-... npx zeta-assistant
|
|
32
|
+
`.trim();
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=cli-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-parser.js","sourceRoot":"","sources":["../../src/utils/cli-parser.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,IAAuB;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE3B,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC9E,MAAM,aAAa,GAAG,gBAAgB;QACpC,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC1C,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,CAAC;IAE7C,OAAO;QACL,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAChD,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QACpD,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC1D,aAAa;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO;;;;;;;;;;;;;;;;;CAiBR,CAAC,IAAI,EAAE,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/whatsapp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpE,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/whatsapp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ZetaConfig } from '../types/index.js';
|
|
2
|
+
export type MessageHandler = (sender: string, body: string) => void;
|
|
3
|
+
export interface WhatsappClientOptions {
|
|
4
|
+
readonly config: ZetaConfig;
|
|
5
|
+
readonly resetSession: boolean;
|
|
6
|
+
readonly onMessage?: MessageHandler;
|
|
7
|
+
}
|
|
8
|
+
export declare class WhatsappClient {
|
|
9
|
+
private readonly client;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
private readonly sessionPath;
|
|
12
|
+
private readonly sentByBot;
|
|
13
|
+
private isReady;
|
|
14
|
+
constructor(options: WhatsappClientOptions);
|
|
15
|
+
initialize(): Promise<void>;
|
|
16
|
+
destroy(): Promise<void>;
|
|
17
|
+
getIsReady(): boolean;
|
|
18
|
+
private clearSession;
|
|
19
|
+
private removeStaleLocks;
|
|
20
|
+
private killOrphanedChrome;
|
|
21
|
+
private registerEventHandlers;
|
|
22
|
+
sendMessage(to: string, text: string): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export declare function initWhatsapp(options: WhatsappClientOptions): Promise<WhatsappClient>;
|
|
25
|
+
//# sourceMappingURL=whatsapp-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whatsapp-client.d.ts","sourceRoot":"","sources":["../../src/whatsapp/whatsapp-client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAKpD,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;CACrC;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAErC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,qBAAqB;IA2BpC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAU9B,UAAU,IAAI,OAAO;IAIrB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,qBAAqB;IA6CvB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAI3D;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CAI1F"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import pkg from 'whatsapp-web.js';
|
|
2
|
+
const { Client, LocalAuth } = pkg;
|
|
3
|
+
import qrcode from 'qrcode-terminal';
|
|
4
|
+
import { rmSync, existsSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
|
+
import { WinstonLogger } from '../logger/index.js';
|
|
8
|
+
export class WhatsappClient {
|
|
9
|
+
client;
|
|
10
|
+
logger = new WinstonLogger(WhatsappClient.name);
|
|
11
|
+
sessionPath;
|
|
12
|
+
// Tracks messages sent by the bot itself to prevent re-processing and infinite loops.
|
|
13
|
+
sentByBot = new Set();
|
|
14
|
+
isReady = false;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.sessionPath = options.config.whatsappSessionPath;
|
|
17
|
+
if (options.resetSession) {
|
|
18
|
+
this.clearSession();
|
|
19
|
+
}
|
|
20
|
+
this.removeStaleLocks();
|
|
21
|
+
this.client = new Client({
|
|
22
|
+
authStrategy: new LocalAuth({
|
|
23
|
+
dataPath: this.sessionPath,
|
|
24
|
+
}),
|
|
25
|
+
puppeteer: {
|
|
26
|
+
headless: true,
|
|
27
|
+
args: [
|
|
28
|
+
'--no-sandbox',
|
|
29
|
+
'--disable-setuid-sandbox',
|
|
30
|
+
'--disable-dev-shm-usage',
|
|
31
|
+
'--disable-gpu',
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
this.registerEventHandlers(options.onMessage);
|
|
36
|
+
}
|
|
37
|
+
async initialize() {
|
|
38
|
+
this.logger.info('Initializing WhatsApp Web client...');
|
|
39
|
+
await this.client.initialize();
|
|
40
|
+
}
|
|
41
|
+
async destroy() {
|
|
42
|
+
this.logger.info('Shutting down WhatsApp Web client...');
|
|
43
|
+
try {
|
|
44
|
+
await this.client.destroy();
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
+
this.logger.error(`Error during shutdown: ${message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
getIsReady() {
|
|
52
|
+
return this.isReady;
|
|
53
|
+
}
|
|
54
|
+
clearSession() {
|
|
55
|
+
this.logger.warn('Resetting WhatsApp session (will require new QR scan)...');
|
|
56
|
+
try {
|
|
57
|
+
rmSync(this.sessionPath, { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
61
|
+
this.logger.error(`Failed to clear session: ${message}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
removeStaleLocks() {
|
|
65
|
+
const lockFiles = [
|
|
66
|
+
join(this.sessionPath, 'session', 'SingletonLock'),
|
|
67
|
+
join(this.sessionPath, 'session', 'SingletonSocket'),
|
|
68
|
+
join(this.sessionPath, 'session', 'SingletonCookie'),
|
|
69
|
+
];
|
|
70
|
+
for (const lockFile of lockFiles) {
|
|
71
|
+
if (existsSync(lockFile)) {
|
|
72
|
+
try {
|
|
73
|
+
rmSync(lockFile, { force: true });
|
|
74
|
+
this.logger.debug(`Removed stale lock: ${lockFile}`);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
78
|
+
this.logger.warn(`Could not remove lock file ${lockFile}: ${message}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
this.killOrphanedChrome();
|
|
83
|
+
}
|
|
84
|
+
killOrphanedChrome() {
|
|
85
|
+
try {
|
|
86
|
+
// Find Chrome processes using this session directory
|
|
87
|
+
const result = execSync(`ps aux | grep -i "chrome" | grep "${this.sessionPath}" | grep -v grep | awk '{print $2}'`, { encoding: 'utf-8' });
|
|
88
|
+
const pids = result.trim().split('\n').filter(Boolean);
|
|
89
|
+
if (pids.length > 0) {
|
|
90
|
+
this.logger.debug(`Found ${String(pids.length)} orphaned Chrome process(es), killing...`);
|
|
91
|
+
for (const pid of pids) {
|
|
92
|
+
execSync(`kill -9 ${pid}`, { stdio: 'ignore' });
|
|
93
|
+
}
|
|
94
|
+
// Give OS time to clean up
|
|
95
|
+
execSync('sleep 1', { stdio: 'ignore' });
|
|
96
|
+
}
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
98
|
+
}
|
|
99
|
+
catch (_) {
|
|
100
|
+
// Ignore errors — Chrome might not be running, which is fine
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
registerEventHandlers(onMessage) {
|
|
104
|
+
this.client.on('qr', (qr) => {
|
|
105
|
+
this.logger.info('QR code received. Scan with WhatsApp on your phone:');
|
|
106
|
+
qrcode.generate(qr, { small: true });
|
|
107
|
+
});
|
|
108
|
+
this.client.on('ready', () => {
|
|
109
|
+
this.isReady = true;
|
|
110
|
+
const info = this.client.info;
|
|
111
|
+
const owner = info?.wid._serialized ?? 'unknown';
|
|
112
|
+
this.logger.info(`Client is ready. Owner: ${owner}`);
|
|
113
|
+
});
|
|
114
|
+
this.client.on('authenticated', () => {
|
|
115
|
+
this.logger.info('Session authenticated successfully.');
|
|
116
|
+
});
|
|
117
|
+
this.client.on('auth_failure', (msg) => {
|
|
118
|
+
this.isReady = false;
|
|
119
|
+
this.logger.error(`Authentication failed: ${msg}`);
|
|
120
|
+
});
|
|
121
|
+
this.client.on('disconnected', (reason) => {
|
|
122
|
+
this.isReady = false;
|
|
123
|
+
this.logger.warn(`Disconnected: ${reason}`);
|
|
124
|
+
});
|
|
125
|
+
this.client.on('message_create', (msg) => {
|
|
126
|
+
if (!msg.fromMe || !msg.body) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
// Since we send messages to our own number, bot replies arrive back as new incoming
|
|
130
|
+
// messages (owner → OpenAI → reply → WhatsApp → same number → triggers onMessage again).
|
|
131
|
+
// We track bot-sent texts in sentByBot to break this infinite loop.
|
|
132
|
+
if (this.sentByBot.has(msg.body)) {
|
|
133
|
+
this.sentByBot.delete(msg.body);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
this.logger.info(`Message from owner: ${msg.body}`);
|
|
137
|
+
onMessage?.(msg.from, msg.body);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
async sendMessage(to, text) {
|
|
141
|
+
this.sentByBot.add(text);
|
|
142
|
+
await this.client.sendMessage(to, text);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export async function initWhatsapp(options) {
|
|
146
|
+
const client = new WhatsappClient(options);
|
|
147
|
+
await client.initialize();
|
|
148
|
+
return client;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=whatsapp-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whatsapp-client.js","sourceRoot":"","sources":["../../src/whatsapp/whatsapp-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zeta-assistant",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A locally running AI operator controlled via WhatsApp Web",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"zeta-assistant": "./dist/main.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -p tsconfig.build.json",
|
|
22
|
+
"dev": "node --loader ts-node/esm src/main.ts",
|
|
23
|
+
"start": "node dist/main.js",
|
|
24
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
25
|
+
"test:coverage": "node --experimental-vm-modules node_modules/.bin/jest --coverage",
|
|
26
|
+
"lint": "eslint src/ tests/",
|
|
27
|
+
"lint:fix": "eslint src/ tests/ --fix",
|
|
28
|
+
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
29
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"prepare": "husky",
|
|
32
|
+
"prepack": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=20.0.0"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"whatsapp",
|
|
39
|
+
"ai",
|
|
40
|
+
"assistant",
|
|
41
|
+
"gpt",
|
|
42
|
+
"automation",
|
|
43
|
+
"cli"
|
|
44
|
+
],
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"openai": "6.22.0",
|
|
48
|
+
"qrcode-terminal": "0.12.0",
|
|
49
|
+
"whatsapp-web.js": "1.34.6",
|
|
50
|
+
"winston": "3.19.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/jest": "^30.0.0",
|
|
54
|
+
"@types/node": "22.13.4",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "8.24.0",
|
|
56
|
+
"@typescript-eslint/parser": "8.24.0",
|
|
57
|
+
"eslint": "9.20.0",
|
|
58
|
+
"husky": "9.1.7",
|
|
59
|
+
"jest": "29.7.0",
|
|
60
|
+
"lint-staged": "15.4.3",
|
|
61
|
+
"prettier": "3.5.1",
|
|
62
|
+
"ts-jest": "29.2.5",
|
|
63
|
+
"ts-node": "10.9.2",
|
|
64
|
+
"typescript": "5.7.3"
|
|
65
|
+
},
|
|
66
|
+
"lint-staged": {
|
|
67
|
+
"*.ts": [
|
|
68
|
+
"eslint --fix",
|
|
69
|
+
"prettier --write"
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
}
|