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.
Files changed (70) hide show
  1. package/README.md +238 -0
  2. package/dist/agent/agent-loop.d.ts +7 -0
  3. package/dist/agent/agent-loop.d.ts.map +1 -0
  4. package/dist/agent/agent-loop.js +34 -0
  5. package/dist/agent/agent-loop.js.map +1 -0
  6. package/dist/agent/index.d.ts +2 -0
  7. package/dist/agent/index.d.ts.map +1 -0
  8. package/dist/agent/index.js +2 -0
  9. package/dist/agent/index.js.map +1 -0
  10. package/dist/agent/planner.d.ts +8 -0
  11. package/dist/agent/planner.d.ts.map +1 -0
  12. package/dist/agent/planner.js +87 -0
  13. package/dist/agent/planner.js.map +1 -0
  14. package/dist/config/config-loader.d.ts +5 -0
  15. package/dist/config/config-loader.d.ts.map +1 -0
  16. package/dist/config/config-loader.js +27 -0
  17. package/dist/config/config-loader.js.map +1 -0
  18. package/dist/config/index.d.ts +2 -0
  19. package/dist/config/index.d.ts.map +1 -0
  20. package/dist/config/index.js +2 -0
  21. package/dist/config/index.js.map +1 -0
  22. package/dist/executor/command-executor.d.ts +7 -0
  23. package/dist/executor/command-executor.d.ts.map +1 -0
  24. package/dist/executor/command-executor.js +34 -0
  25. package/dist/executor/command-executor.js.map +1 -0
  26. package/dist/executor/index.d.ts +2 -0
  27. package/dist/executor/index.d.ts.map +1 -0
  28. package/dist/executor/index.js +2 -0
  29. package/dist/executor/index.js.map +1 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +4 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/logger/index.d.ts +3 -0
  35. package/dist/logger/index.d.ts.map +1 -0
  36. package/dist/logger/index.js +2 -0
  37. package/dist/logger/index.js.map +1 -0
  38. package/dist/logger/logger.d.ts +8 -0
  39. package/dist/logger/logger.d.ts.map +1 -0
  40. package/dist/logger/logger.js +2 -0
  41. package/dist/logger/logger.js.map +1 -0
  42. package/dist/logger/winston-logger.d.ts +19 -0
  43. package/dist/logger/winston-logger.d.ts.map +1 -0
  44. package/dist/logger/winston-logger.js +65 -0
  45. package/dist/logger/winston-logger.js.map +1 -0
  46. package/dist/main.d.ts +3 -0
  47. package/dist/main.d.ts.map +1 -0
  48. package/dist/main.js +67 -0
  49. package/dist/main.js.map +1 -0
  50. package/dist/types/index.d.ts +24 -0
  51. package/dist/types/index.d.ts.map +1 -0
  52. package/dist/types/index.js +2 -0
  53. package/dist/types/index.js.map +1 -0
  54. package/dist/utils/cli-parser.d.ts +4 -0
  55. package/dist/utils/cli-parser.d.ts.map +1 -0
  56. package/dist/utils/cli-parser.js +34 -0
  57. package/dist/utils/cli-parser.js.map +1 -0
  58. package/dist/utils/index.d.ts +2 -0
  59. package/dist/utils/index.d.ts.map +1 -0
  60. package/dist/utils/index.js +2 -0
  61. package/dist/utils/index.js.map +1 -0
  62. package/dist/whatsapp/index.d.ts +3 -0
  63. package/dist/whatsapp/index.d.ts.map +1 -0
  64. package/dist/whatsapp/index.js +2 -0
  65. package/dist/whatsapp/index.js.map +1 -0
  66. package/dist/whatsapp/whatsapp-client.d.ts +25 -0
  67. package/dist/whatsapp/whatsapp-client.d.ts.map +1 -0
  68. package/dist/whatsapp/whatsapp-client.js +150 -0
  69. package/dist/whatsapp/whatsapp-client.js.map +1 -0
  70. 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,7 @@
1
+ export declare class AgentLoop {
2
+ private readonly planner;
3
+ private readonly executor;
4
+ constructor(apiKey: string);
5
+ run(userMessage: string): Promise<string>;
6
+ }
7
+ //# sourceMappingURL=agent-loop.d.ts.map
@@ -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,2 @@
1
+ export { AgentLoop } from './agent-loop.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { AgentLoop } from './agent-loop.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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,2 @@
1
+ export { initConfig, ensureDirectory, ensureZetaDirectories } from './config-loader.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { initConfig, ensureDirectory, ensureZetaDirectories } from './config-loader.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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,7 @@
1
+ import type { CommandResult } from '../types/index.js';
2
+ export declare class CommandExecutor {
3
+ private readonly logger;
4
+ run(commands: readonly string[]): Promise<CommandResult[]>;
5
+ private runOne;
6
+ }
7
+ //# sourceMappingURL=command-executor.d.ts.map
@@ -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,2 @@
1
+ export { CommandExecutor } from './command-executor.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { CommandExecutor } from './command-executor.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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"}
@@ -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,4 @@
1
+ export { initConfig } from './config/index.js';
2
+ export { WhatsappClient, initWhatsapp } from './whatsapp/index.js';
3
+ export { WinstonLogger, initLoggerTransports } from './logger/index.js';
4
+ //# sourceMappingURL=index.js.map
@@ -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,3 @@
1
+ export type { Logger, LogLevel } from './logger.js';
2
+ export { WinstonLogger, initLoggerTransports } from './winston-logger.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { WinstonLogger, initLoggerTransports } from './winston-logger.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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,8 @@
1
+ export type LogLevel = 'info' | 'warn' | 'error' | 'debug';
2
+ export interface Logger {
3
+ info(message: string): void;
4
+ warn(message: string): void;
5
+ error(message: string): void;
6
+ debug(message: string): void;
7
+ }
8
+ //# sourceMappingURL=logger.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logger.js.map
@@ -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,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=main.d.ts.map
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;AAEzC,SAAS,UAAU;IACjB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;IAC9D,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC;AAED,SAAS,oBAAoB,CAAC,aAA4B;IACxD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,CACV,kGAAkG,CACnG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAwB;IACpD,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAc,EAAiB,EAAE;QACvD,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,+BAA+B,CAAC,CAAC;QAC/D,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAExC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IAExC,MAAM,CAAC,IAAI,CAAC,mBAAmB,UAAU,EAAE,cAAc,CAAC,CAAC;IAE3D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAErC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC;QAClC,MAAM;QACN,YAAY,EAAE,IAAI,CAAC,aAAa;QAChC,SAAS,EAAE,CAAC,MAAc,EAAE,IAAY,EAAE,EAAE;YAC1C,SAAS;iBACN,GAAG,CAAC,IAAI,CAAC;iBACT,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACpB,MAAM,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,MAAM,CAAC,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;QACP,CAAC;KACF,CAAC,CAAC;IAEH,oBAAoB,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { CliArgs } from '../types/index.js';
2
+ export declare function parseCliArgs(argv: readonly string[]): CliArgs;
3
+ export declare function getHelpText(): string;
4
+ //# sourceMappingURL=cli-parser.d.ts.map
@@ -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,2 @@
1
+ export { parseCliArgs, getHelpText } from './cli-parser.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { parseCliArgs, getHelpText } from './cli-parser.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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,3 @@
1
+ export { WhatsappClient, initWhatsapp } from './whatsapp-client.js';
2
+ export type { WhatsappClientOptions, MessageHandler } from './whatsapp-client.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { WhatsappClient, initWhatsapp } from './whatsapp-client.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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
+ }