owpenwork 0.1.2 → 0.1.4
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 +14 -27
- package/dist/cli.js +60 -20
- package/install.sh +2 -3
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -19,12 +19,10 @@ npm install -g owpenwork
|
|
|
19
19
|
Quick run without install:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
npx owpenwork
|
|
23
|
-
npx owpenwork whatsapp login
|
|
24
|
-
npx owpenwork start
|
|
22
|
+
npx owpenwork
|
|
25
23
|
```
|
|
26
24
|
|
|
27
|
-
Then follow the
|
|
25
|
+
Then follow the prompts (setup, QR login, start).
|
|
28
26
|
|
|
29
27
|
1) One-command setup (installs deps, builds, creates `.env` if missing):
|
|
30
28
|
|
|
@@ -43,25 +41,13 @@ Recommended:
|
|
|
43
41
|
- `OPENCODE_SERVER_USERNAME`
|
|
44
42
|
- `OPENCODE_SERVER_PASSWORD`
|
|
45
43
|
|
|
46
|
-
3) Run
|
|
44
|
+
3) Run owpenwork and follow the guided setup:
|
|
47
45
|
|
|
48
46
|
```bash
|
|
49
|
-
owpenwork
|
|
47
|
+
owpenwork
|
|
50
48
|
```
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
owpenwork whatsapp login
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
5) Start the bridge:
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
owpenwork start
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Owpenbot keeps the WhatsApp session alive once connected.
|
|
50
|
+
Owpenwork keeps the WhatsApp session alive once connected.
|
|
65
51
|
|
|
66
52
|
6) Pair a user with the bot (only if DM policy is pairing):
|
|
67
53
|
|
|
@@ -75,8 +61,8 @@ Owpenbot keeps the WhatsApp session alive once connected.
|
|
|
75
61
|
|
|
76
62
|
Use your own WhatsApp account as the bot and test from a second number you control.
|
|
77
63
|
|
|
78
|
-
1) Run `owpenwork
|
|
79
|
-
2)
|
|
64
|
+
1) Run `owpenwork` and choose “personal number.”
|
|
65
|
+
2) Scan the QR when prompted.
|
|
80
66
|
3) Message yourself or from a second number; your number is already allowlisted.
|
|
81
67
|
|
|
82
68
|
Note: WhatsApp’s “message yourself” thread is not reliable for bot testing.
|
|
@@ -86,8 +72,8 @@ Note: WhatsApp’s “message yourself” thread is not reliable for bot testing
|
|
|
86
72
|
Use a separate WhatsApp number as the bot account so it stays independent from your personal chat history.
|
|
87
73
|
|
|
88
74
|
1) Create a new WhatsApp account for the dedicated number.
|
|
89
|
-
2) Run `owpenwork
|
|
90
|
-
3)
|
|
75
|
+
2) Run `owpenwork` and choose “dedicated number.”
|
|
76
|
+
3) Scan the QR when prompted.
|
|
91
77
|
4) If DM policy is pairing, approve codes with `owpenwork pairing approve <code>`.
|
|
92
78
|
|
|
93
79
|
## Telegram (Untested)
|
|
@@ -99,9 +85,8 @@ Telegram support is wired but not E2E tested yet. To try it:
|
|
|
99
85
|
## Commands
|
|
100
86
|
|
|
101
87
|
```bash
|
|
102
|
-
owpenwork
|
|
103
|
-
owpenwork
|
|
104
|
-
owpenwork start
|
|
88
|
+
owpenwork
|
|
89
|
+
owpenwork --non-interactive
|
|
105
90
|
owpenwork pairing list
|
|
106
91
|
owpenwork pairing approve <code>
|
|
107
92
|
owpenwork status
|
|
@@ -110,7 +95,7 @@ owpenwork status
|
|
|
110
95
|
## Defaults
|
|
111
96
|
|
|
112
97
|
- SQLite at `~/.owpenbot/owpenbot.db` unless overridden.
|
|
113
|
-
- Config stored at `~/.owpenbot/owpenbot.json` (created by `
|
|
98
|
+
- Config stored at `~/.owpenbot/owpenbot.json` (created by `owpenwork` or `owpenwork setup`).
|
|
114
99
|
- DM policy defaults to `pairing` unless changed in setup.
|
|
115
100
|
- Group chats are disabled unless `GROUPS_ENABLED=true`.
|
|
116
101
|
|
|
@@ -119,4 +104,6 @@ owpenwork status
|
|
|
119
104
|
```bash
|
|
120
105
|
pnpm -C packages/owpenbot test:unit
|
|
121
106
|
pnpm -C packages/owpenbot test:smoke
|
|
107
|
+
pnpm -C packages/owpenbot test:cli
|
|
108
|
+
pnpm -C packages/owpenbot test:npx
|
|
122
109
|
```
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
3
4
|
import { createInterface } from "node:readline/promises";
|
|
4
5
|
import { Command } from "commander";
|
|
5
6
|
import { startBridge } from "./bridge.js";
|
|
@@ -10,8 +11,11 @@ import { loginWhatsApp, unpairWhatsApp } from "./whatsapp.js";
|
|
|
10
11
|
const program = new Command();
|
|
11
12
|
program
|
|
12
13
|
.name("owpenbot")
|
|
14
|
+
.version("0.1.3")
|
|
13
15
|
.description("OpenCode WhatsApp + Telegram bridge")
|
|
14
|
-
.argument("[path]")
|
|
16
|
+
.argument("[path]")
|
|
17
|
+
.option("--non-interactive", "Run setup defaults and exit", false)
|
|
18
|
+
.option("--check", "Validate config/auth and exit", false);
|
|
15
19
|
const runStart = async (pathOverride) => {
|
|
16
20
|
if (pathOverride?.trim()) {
|
|
17
21
|
process.env.OPENCODE_DIRECTORY = pathOverride.trim();
|
|
@@ -22,7 +26,7 @@ const runStart = async (pathOverride) => {
|
|
|
22
26
|
process.env.OPENCODE_DIRECTORY = config.opencodeDirectory;
|
|
23
27
|
}
|
|
24
28
|
const bridge = await startBridge(config, logger);
|
|
25
|
-
logger.info("Commands:
|
|
29
|
+
logger.info("Commands: owpenwork whatsapp login, owpenwork pairing list, owpenwork status");
|
|
26
30
|
const shutdown = async () => {
|
|
27
31
|
logger.info("shutting down");
|
|
28
32
|
await bridge.stop();
|
|
@@ -31,26 +35,10 @@ const runStart = async (pathOverride) => {
|
|
|
31
35
|
process.on("SIGINT", shutdown);
|
|
32
36
|
process.on("SIGTERM", shutdown);
|
|
33
37
|
};
|
|
34
|
-
|
|
35
|
-
.command("start")
|
|
36
|
-
.description("Start the bridge")
|
|
37
|
-
.action(() => runStart());
|
|
38
|
-
program.action((pathArg) => {
|
|
39
|
-
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
40
|
-
program.outputHelp();
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
return runStart(pathArg);
|
|
44
|
-
});
|
|
45
|
-
program
|
|
46
|
-
.command("setup")
|
|
47
|
-
.description("Create or update owpenbot.json for WhatsApp")
|
|
48
|
-
.option("--non-interactive", "Write defaults without prompts", false)
|
|
49
|
-
.action(async (opts) => {
|
|
50
|
-
const config = loadConfig(process.env, { requireOpencode: false });
|
|
38
|
+
async function runSetupWizard(config, nonInteractive) {
|
|
51
39
|
const { config: existing } = readConfigFile(config.configPath);
|
|
52
40
|
const next = existing ?? { version: 1 };
|
|
53
|
-
if (
|
|
41
|
+
if (nonInteractive) {
|
|
54
42
|
next.version = 1;
|
|
55
43
|
next.channels = next.channels ?? {};
|
|
56
44
|
next.channels.whatsapp = {
|
|
@@ -125,6 +113,58 @@ program
|
|
|
125
113
|
};
|
|
126
114
|
writeConfigFile(config.configPath, next);
|
|
127
115
|
console.log(`Wrote ${config.configPath}`);
|
|
116
|
+
}
|
|
117
|
+
async function runGuidedFlow(pathArg, opts) {
|
|
118
|
+
if (pathArg?.trim()) {
|
|
119
|
+
process.env.OPENCODE_DIRECTORY = pathArg.trim();
|
|
120
|
+
}
|
|
121
|
+
let config = loadConfig(process.env, { requireOpencode: false });
|
|
122
|
+
if (!process.env.OPENCODE_DIRECTORY) {
|
|
123
|
+
process.env.OPENCODE_DIRECTORY = config.opencodeDirectory;
|
|
124
|
+
}
|
|
125
|
+
if (opts.check) {
|
|
126
|
+
const authPath = path.join(config.whatsappAuthDir, "creds.json");
|
|
127
|
+
const linked = fs.existsSync(authPath);
|
|
128
|
+
const cfgExists = fs.existsSync(config.configPath);
|
|
129
|
+
console.log(`Config: ${cfgExists ? "yes" : "no"}`);
|
|
130
|
+
console.log(`WhatsApp linked: ${linked ? "yes" : "no"}`);
|
|
131
|
+
process.exit(linked && cfgExists ? 0 : 1);
|
|
132
|
+
}
|
|
133
|
+
const cfgExists = fs.existsSync(config.configPath);
|
|
134
|
+
const cfgHasWhatsApp = config.configFile.channels?.whatsapp;
|
|
135
|
+
if (!cfgExists || !cfgHasWhatsApp) {
|
|
136
|
+
await runSetupWizard(config, opts.nonInteractive);
|
|
137
|
+
if (opts.nonInteractive) {
|
|
138
|
+
console.log("Next: owpenwork whatsapp login");
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
config = loadConfig(process.env, { requireOpencode: false });
|
|
143
|
+
const authPath = path.join(config.whatsappAuthDir, "creds.json");
|
|
144
|
+
if (!fs.existsSync(authPath)) {
|
|
145
|
+
await loginWhatsApp(config, createLogger(config.logLevel));
|
|
146
|
+
}
|
|
147
|
+
await runStart(pathArg);
|
|
148
|
+
}
|
|
149
|
+
program
|
|
150
|
+
.command("start")
|
|
151
|
+
.description("Start the bridge")
|
|
152
|
+
.action(() => runStart());
|
|
153
|
+
program.action((pathArg) => {
|
|
154
|
+
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
155
|
+
program.outputHelp();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const opts = program.opts();
|
|
159
|
+
return runGuidedFlow(pathArg, { nonInteractive: Boolean(opts.nonInteractive), check: Boolean(opts.check) });
|
|
160
|
+
});
|
|
161
|
+
program
|
|
162
|
+
.command("setup")
|
|
163
|
+
.description("Create or update owpenbot.json for WhatsApp")
|
|
164
|
+
.option("--non-interactive", "Write defaults without prompts", false)
|
|
165
|
+
.action(async (opts) => {
|
|
166
|
+
const config = loadConfig(process.env, { requireOpencode: false });
|
|
167
|
+
await runSetupWizard(config, Boolean(opts.nonInteractive));
|
|
128
168
|
});
|
|
129
169
|
program
|
|
130
170
|
.command("pairing-code")
|
package/install.sh
CHANGED
|
@@ -140,9 +140,8 @@ cat <<EOF
|
|
|
140
140
|
Owpenbot installed.
|
|
141
141
|
|
|
142
142
|
Next steps:
|
|
143
|
-
1) Run
|
|
144
|
-
2)
|
|
145
|
-
3) Start bridge: owpenwork start
|
|
143
|
+
1) Run owpenwork: owpenwork
|
|
144
|
+
2) Follow the guided setup + QR login
|
|
146
145
|
|
|
147
146
|
Owpenbot will print a QR code during login and keep the session alive.
|
|
148
147
|
EOF
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "owpenwork",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "WhatsApp bridge for a running OpenCode server",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
36
36
|
"setup": "node scripts/setup.mjs",
|
|
37
37
|
"test:unit": "pnpm build && node --test test/*.test.js",
|
|
38
|
-
"test:smoke": "node scripts/smoke.mjs"
|
|
38
|
+
"test:smoke": "node scripts/smoke.mjs",
|
|
39
|
+
"test:cli": "pnpm build && node scripts/test-cli.mjs",
|
|
40
|
+
"test:npx": "node scripts/test-npx.mjs"
|
|
39
41
|
},
|
|
40
42
|
"dependencies": {
|
|
41
43
|
"@opencode-ai/sdk": "^1.1.19",
|