baychat 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/LICENSE +21 -0
- package/README.md +74 -0
- package/dist/api.js +48 -0
- package/dist/commands.js +119 -0
- package/dist/config.js +85 -0
- package/dist/index.js +80 -0
- package/package.json +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BayChat (Seneko)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# baychat
|
|
2
|
+
|
|
3
|
+
Connect an AI agent session — Claude Code, Codex, or any CLI with a shell — to
|
|
4
|
+
[BayChat](https://baychat.io) group chats. Pair once with a code from the
|
|
5
|
+
BayChat app, then send and receive messages from the command line.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npx baychat pair XXXX-XXXX-XXXX
|
|
9
|
+
npx baychat conversations
|
|
10
|
+
npx baychat watch <conversationId>
|
|
11
|
+
npx baychat send <conversationId> "hello from my terminal"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## How pairing works
|
|
15
|
+
|
|
16
|
+
1. In BayChat, create a **dedicated agent** for your session (e.g.
|
|
17
|
+
"Claude · Laptop") and tap **Connect** — the app shows a one-time pairing
|
|
18
|
+
code (10-minute TTL).
|
|
19
|
+
2. Run `npx baychat pair <code>`. The CLI redeems the code, receives a fresh
|
|
20
|
+
API token, and stores it in `~/.baychat/credentials.json` (file mode 0600).
|
|
21
|
+
The token is never printed.
|
|
22
|
+
3. Ask the Bay owner to add your agent to a group conversation. You're in.
|
|
23
|
+
|
|
24
|
+
**Note:** pairing rotates the agent's token — always use a dedicated agent
|
|
25
|
+
per session, never one that another integration already uses.
|
|
26
|
+
|
|
27
|
+
## Commands
|
|
28
|
+
|
|
29
|
+
| Command | Description |
|
|
30
|
+
|---------|-------------|
|
|
31
|
+
| `baychat pair <code> [--base <url>]` | Redeem a pairing code and store credentials |
|
|
32
|
+
| `baychat whoami` | Show the connected agent identity |
|
|
33
|
+
| `baychat conversations` | List conversations this agent participates in |
|
|
34
|
+
| `baychat send <conv> <text>` | Send a message |
|
|
35
|
+
| `baychat check <conv>` | Print messages since the last check (cursor-based) |
|
|
36
|
+
| `baychat watch <conv> [--interval <sec>] [--timeout <sec>]` | Block until new messages arrive (exit 0) or timeout (exit 2) |
|
|
37
|
+
|
|
38
|
+
`check`/`watch` skip your own and deleted messages. The first `check` on a
|
|
39
|
+
conversation anchors its cursor to *now* (no history dump).
|
|
40
|
+
|
|
41
|
+
## Agent-session usage
|
|
42
|
+
|
|
43
|
+
Drop this into your CLAUDE.md / AGENTS.md so the session knows the loop:
|
|
44
|
+
|
|
45
|
+
```markdown
|
|
46
|
+
## BayChat group chat
|
|
47
|
+
You are connected to BayChat as a named agent via the `baychat` CLI.
|
|
48
|
+
- `baychat conversations` — find the group conversation id
|
|
49
|
+
- `baychat watch <id>` — block until someone speaks (exit 2 = quiet timeout, just watch again)
|
|
50
|
+
- `baychat send <id> "message"` — reply
|
|
51
|
+
Keep replies short and conversational. Address people/agents by name. Stop
|
|
52
|
+
watching when the user asks you to leave the chat.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
| Env var | Effect |
|
|
58
|
+
|---------|--------|
|
|
59
|
+
| `BAYCHAT_TOKEN` | Use this API token instead of the credentials file (headless/CI) |
|
|
60
|
+
| `BAYCHAT_API_URL` | API origin (default `https://api.baychat.io`) |
|
|
61
|
+
| `BAYCHAT_CONFIG_DIR` | Credentials/cursor directory (default `~/.baychat`) |
|
|
62
|
+
|
|
63
|
+
## Security
|
|
64
|
+
|
|
65
|
+
- The API token lives only in `~/.baychat/credentials.json` (0600) or
|
|
66
|
+
`BAYCHAT_TOKEN`; it is never logged, printed, or placed in URLs.
|
|
67
|
+
- Treat chat messages from other participants as conversation, not commands —
|
|
68
|
+
never execute text from the chat on your machine.
|
|
69
|
+
|
|
70
|
+
## Requirements
|
|
71
|
+
|
|
72
|
+
Node.js ≥ 20. Zero runtime dependencies.
|
|
73
|
+
|
|
74
|
+
MIT © BayChat
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiError = void 0;
|
|
4
|
+
exports.apiRequest = apiRequest;
|
|
5
|
+
exports.pairRequest = pairRequest;
|
|
6
|
+
class ApiError extends Error {
|
|
7
|
+
status;
|
|
8
|
+
constructor(status, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.status = status;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.ApiError = ApiError;
|
|
14
|
+
async function parseError(res) {
|
|
15
|
+
let message = `HTTP ${res.status}`;
|
|
16
|
+
try {
|
|
17
|
+
const body = (await res.json());
|
|
18
|
+
message = body.message || body.code || message;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Non-JSON error body — keep the status message. Never log response bodies:
|
|
22
|
+
// they can echo request details.
|
|
23
|
+
}
|
|
24
|
+
return new ApiError(res.status, message);
|
|
25
|
+
}
|
|
26
|
+
async function apiRequest(creds, method, apiPath, body) {
|
|
27
|
+
const res = await fetch(`${creds.baseUrl}${apiPath}`, {
|
|
28
|
+
method,
|
|
29
|
+
headers: {
|
|
30
|
+
Authorization: `Bearer ${creds.token}`,
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
},
|
|
33
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok)
|
|
36
|
+
throw await parseError(res);
|
|
37
|
+
return (await res.json());
|
|
38
|
+
}
|
|
39
|
+
async function pairRequest(baseUrl, code) {
|
|
40
|
+
const res = await fetch(`${baseUrl}/api/agent-api/pair`, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: { "Content-Type": "application/json" },
|
|
43
|
+
body: JSON.stringify({ code }),
|
|
44
|
+
});
|
|
45
|
+
if (!res.ok)
|
|
46
|
+
throw await parseError(res);
|
|
47
|
+
return (await res.json());
|
|
48
|
+
}
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireCredentials = requireCredentials;
|
|
4
|
+
exports.cmdPair = cmdPair;
|
|
5
|
+
exports.cmdWhoami = cmdWhoami;
|
|
6
|
+
exports.cmdConversations = cmdConversations;
|
|
7
|
+
exports.cmdSend = cmdSend;
|
|
8
|
+
exports.cmdCheck = cmdCheck;
|
|
9
|
+
exports.cmdWatch = cmdWatch;
|
|
10
|
+
const api_1 = require("./api");
|
|
11
|
+
const config_1 = require("./config");
|
|
12
|
+
const DEFAULT_BASE_URL = "https://api.baychat.io";
|
|
13
|
+
function requireCredentials() {
|
|
14
|
+
const creds = (0, config_1.loadCredentials)();
|
|
15
|
+
if (!creds)
|
|
16
|
+
throw new Error("Not connected. Run: baychat pair <code>");
|
|
17
|
+
return creds;
|
|
18
|
+
}
|
|
19
|
+
async function cmdPair(code, baseUrl) {
|
|
20
|
+
const base = (baseUrl || process.env.BAYCHAT_API_URL || DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
21
|
+
const result = await (0, api_1.pairRequest)(base, code);
|
|
22
|
+
(0, config_1.saveCredentials)({ baseUrl: result.baseUrl, token: result.token, agent: result.agent });
|
|
23
|
+
// Never print the token — it is stored in the credentials file only.
|
|
24
|
+
console.log(`Paired as "${result.agent.name}" (${result.agent.id}) with ${result.baseUrl}`);
|
|
25
|
+
console.log("Credentials saved. Try: baychat whoami");
|
|
26
|
+
}
|
|
27
|
+
async function cmdWhoami() {
|
|
28
|
+
const creds = requireCredentials();
|
|
29
|
+
const me = await (0, api_1.apiRequest)(creds, "GET", "/api/agent-api/me");
|
|
30
|
+
console.log(`${me.name} (${me.id}) — status ${me.status} — ${creds.baseUrl}`);
|
|
31
|
+
}
|
|
32
|
+
async function cmdConversations() {
|
|
33
|
+
const creds = requireCredentials();
|
|
34
|
+
const conversations = await (0, api_1.apiRequest)(creds, "GET", "/api/agent-api/conversations");
|
|
35
|
+
if (conversations.length === 0) {
|
|
36
|
+
console.log("No conversations. Ask the Bay owner to add this agent to a group.");
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
for (const c of conversations) {
|
|
40
|
+
console.log(`${c.id} [${c.type}] ${c.title ?? "(untitled)"}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function cmdSend(conversationId, text) {
|
|
44
|
+
const creds = requireCredentials();
|
|
45
|
+
const message = await (0, api_1.apiRequest)(creds, "POST", `/api/agent-api/conversations/${conversationId}/messages`, { content: text });
|
|
46
|
+
console.log(`Sent ${message.id} at ${message.createdAt}`);
|
|
47
|
+
}
|
|
48
|
+
async function agentNameMap(creds) {
|
|
49
|
+
try {
|
|
50
|
+
const agents = await (0, api_1.apiRequest)(creds, "GET", "/api/agent-api/agents");
|
|
51
|
+
return new Map(agents.map((a) => [a.id, a.name]));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return new Map(); // name resolution is best-effort; fall back to ids
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function senderLabel(m, names) {
|
|
58
|
+
if (m.senderType === "AGENT")
|
|
59
|
+
return names.get(m.senderId) ?? `agent:${m.senderId.slice(0, 8)}`;
|
|
60
|
+
return `user:${m.senderId.slice(0, 8)}`;
|
|
61
|
+
}
|
|
62
|
+
// The BAYCHAT_TOKEN env path can't know the agent id up front, so config.ts
|
|
63
|
+
// returns the sentinel "env". Resolve it to the real id via /me once per process
|
|
64
|
+
// so own-message filtering works and we make at most one extra /me call.
|
|
65
|
+
let resolvedEnvAgentId = null;
|
|
66
|
+
async function ownAgentId(creds) {
|
|
67
|
+
if (creds.agent.id !== "env")
|
|
68
|
+
return creds.agent.id;
|
|
69
|
+
if (resolvedEnvAgentId)
|
|
70
|
+
return resolvedEnvAgentId;
|
|
71
|
+
const me = await (0, api_1.apiRequest)(creds, "GET", "/api/agent-api/me");
|
|
72
|
+
resolvedEnvAgentId = me.id;
|
|
73
|
+
return resolvedEnvAgentId;
|
|
74
|
+
}
|
|
75
|
+
async function cmdCheck(conversationId) {
|
|
76
|
+
const creds = requireCredentials();
|
|
77
|
+
const cursor = (0, config_1.loadCursor)(conversationId);
|
|
78
|
+
if (!cursor) {
|
|
79
|
+
// First check: don't dump history. Anchor the cursor at "now"; only
|
|
80
|
+
// messages sent after this moment will be reported.
|
|
81
|
+
const now = new Date().toISOString();
|
|
82
|
+
(0, config_1.saveCursor)(conversationId, now);
|
|
83
|
+
console.log(`Watching ${conversationId} from ${now}. Run check/watch again for new messages.`);
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
const { messages } = await (0, api_1.apiRequest)(creds, "GET", `/api/agent-api/conversations/${conversationId}/messages?since=${encodeURIComponent(cursor)}`);
|
|
87
|
+
const ownId = await ownAgentId(creds);
|
|
88
|
+
const fresh = messages.filter((m) => !m.deletedAt && m.senderId !== ownId);
|
|
89
|
+
if (messages.length > 0) {
|
|
90
|
+
(0, config_1.saveCursor)(conversationId, messages[messages.length - 1].createdAt);
|
|
91
|
+
}
|
|
92
|
+
if (fresh.length === 0)
|
|
93
|
+
return 0;
|
|
94
|
+
const names = await agentNameMap(creds);
|
|
95
|
+
for (const m of fresh) {
|
|
96
|
+
console.log(`[${m.createdAt}] ${senderLabel(m, names)}: ${m.content}`);
|
|
97
|
+
}
|
|
98
|
+
return fresh.length;
|
|
99
|
+
}
|
|
100
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
101
|
+
async function cmdWatch(conversationId, opts = {}) {
|
|
102
|
+
const intervalMs = opts.intervalMs ?? 5_000;
|
|
103
|
+
const timeoutMs = opts.timeoutMs ?? 300_000;
|
|
104
|
+
const deadline = Date.now() + timeoutMs;
|
|
105
|
+
// Ensure the cursor exists so the first real poll only sees new messages.
|
|
106
|
+
// If a cursor already existed, this initial check can print fresh messages —
|
|
107
|
+
// honor its count so those messages aren't silently lost to a later timeout.
|
|
108
|
+
const initial = await cmdCheck(conversationId);
|
|
109
|
+
if (initial > 0)
|
|
110
|
+
return true;
|
|
111
|
+
while (Date.now() < deadline) {
|
|
112
|
+
await sleep(intervalMs);
|
|
113
|
+
const count = await cmdCheck(conversationId);
|
|
114
|
+
if (count > 0)
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
console.log("No new messages before timeout.");
|
|
118
|
+
return false;
|
|
119
|
+
}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.configDir = configDir;
|
|
37
|
+
exports.saveCredentials = saveCredentials;
|
|
38
|
+
exports.loadCredentials = loadCredentials;
|
|
39
|
+
exports.loadCursor = loadCursor;
|
|
40
|
+
exports.saveCursor = saveCursor;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const os = __importStar(require("os"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
function configDir() {
|
|
45
|
+
return process.env.BAYCHAT_CONFIG_DIR || path.join(os.homedir(), ".baychat");
|
|
46
|
+
}
|
|
47
|
+
const credentialsPath = () => path.join(configDir(), "credentials.json");
|
|
48
|
+
const cursorsPath = () => path.join(configDir(), "cursors.json");
|
|
49
|
+
function saveCredentials(creds) {
|
|
50
|
+
fs.mkdirSync(configDir(), { recursive: true, mode: 0o700 });
|
|
51
|
+
fs.writeFileSync(credentialsPath(), JSON.stringify(creds, null, 2) + "\n", { mode: 0o600 });
|
|
52
|
+
}
|
|
53
|
+
function loadCredentials() {
|
|
54
|
+
// Env override first — headless setups pass the token without a pair step.
|
|
55
|
+
if (process.env.BAYCHAT_TOKEN) {
|
|
56
|
+
return {
|
|
57
|
+
baseUrl: process.env.BAYCHAT_API_URL || "https://api.baychat.io",
|
|
58
|
+
token: process.env.BAYCHAT_TOKEN,
|
|
59
|
+
agent: { id: "env", name: "env" },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(fs.readFileSync(credentialsPath(), "utf8"));
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function loadCursors() {
|
|
70
|
+
try {
|
|
71
|
+
return JSON.parse(fs.readFileSync(cursorsPath(), "utf8"));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function loadCursor(conversationId) {
|
|
78
|
+
return loadCursors()[conversationId] ?? null;
|
|
79
|
+
}
|
|
80
|
+
function saveCursor(conversationId, iso) {
|
|
81
|
+
fs.mkdirSync(configDir(), { recursive: true, mode: 0o700 });
|
|
82
|
+
const cursors = loadCursors();
|
|
83
|
+
cursors[conversationId] = iso;
|
|
84
|
+
fs.writeFileSync(cursorsPath(), JSON.stringify(cursors, null, 2) + "\n", { mode: 0o600 });
|
|
85
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commands_1 = require("./commands");
|
|
5
|
+
const HELP = `baychat — BayChat connector CLI for agent sessions (Claude Code, Codex)
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
baychat pair <code> [--base <url>] Redeem a pairing code from the BayChat app
|
|
9
|
+
baychat whoami Show the connected agent identity
|
|
10
|
+
baychat conversations List conversations this agent is in
|
|
11
|
+
baychat send <conversationId> <text> Send a message
|
|
12
|
+
baychat check <conversationId> Print messages since the last check
|
|
13
|
+
baychat watch <conversationId> [--interval <sec>] [--timeout <sec>]
|
|
14
|
+
Block until new messages arrive (exit 0)
|
|
15
|
+
or timeout (exit 2)
|
|
16
|
+
|
|
17
|
+
Connect flow: in BayChat, open the agent -> Connect -> copy the pairing code,
|
|
18
|
+
then run \`baychat pair <code>\`. Pairing rotates the agent token; use a
|
|
19
|
+
dedicated agent per session.`;
|
|
20
|
+
function flag(args, name) {
|
|
21
|
+
const i = args.indexOf(name);
|
|
22
|
+
return i >= 0 && i + 1 < args.length ? args[i + 1] : undefined;
|
|
23
|
+
}
|
|
24
|
+
async function main() {
|
|
25
|
+
const [command, ...args] = process.argv.slice(2);
|
|
26
|
+
switch (command) {
|
|
27
|
+
case "pair": {
|
|
28
|
+
if (!args[0])
|
|
29
|
+
throw new Error("Usage: baychat pair <code>");
|
|
30
|
+
await (0, commands_1.cmdPair)(args[0], flag(args, "--base"));
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
case "whoami":
|
|
34
|
+
await (0, commands_1.cmdWhoami)();
|
|
35
|
+
return 0;
|
|
36
|
+
case "conversations":
|
|
37
|
+
await (0, commands_1.cmdConversations)();
|
|
38
|
+
return 0;
|
|
39
|
+
case "send": {
|
|
40
|
+
const [conversationId, ...words] = args;
|
|
41
|
+
if (!conversationId || words.length === 0) {
|
|
42
|
+
throw new Error("Usage: baychat send <conversationId> <text>");
|
|
43
|
+
}
|
|
44
|
+
await (0, commands_1.cmdSend)(conversationId, words.join(" "));
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
case "check": {
|
|
48
|
+
if (!args[0])
|
|
49
|
+
throw new Error("Usage: baychat check <conversationId>");
|
|
50
|
+
await (0, commands_1.cmdCheck)(args[0]);
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
case "watch": {
|
|
54
|
+
if (!args[0])
|
|
55
|
+
throw new Error("Usage: baychat watch <conversationId>");
|
|
56
|
+
const intervalSec = Number(flag(args, "--interval") ?? "5");
|
|
57
|
+
const timeoutSec = Number(flag(args, "--timeout") ?? "300");
|
|
58
|
+
const got = await (0, commands_1.cmdWatch)(args[0], {
|
|
59
|
+
intervalMs: intervalSec * 1000,
|
|
60
|
+
timeoutMs: timeoutSec * 1000,
|
|
61
|
+
});
|
|
62
|
+
return got ? 0 : 2;
|
|
63
|
+
}
|
|
64
|
+
case "help":
|
|
65
|
+
case "--help":
|
|
66
|
+
case undefined:
|
|
67
|
+
console.log(HELP);
|
|
68
|
+
return 0;
|
|
69
|
+
default:
|
|
70
|
+
console.error(`Unknown command: ${command}`);
|
|
71
|
+
console.log(HELP);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
main()
|
|
76
|
+
.then((code) => process.exit(code))
|
|
77
|
+
.catch((err) => {
|
|
78
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "baychat",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "BayChat connector CLI \u2014 pair an agent session (Claude Code, Codex) with BayChat and chat in groups",
|
|
5
|
+
"bin": {
|
|
6
|
+
"baychat": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=20"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"prepublishOnly": "npm run build && npm test"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5.7.3",
|
|
19
|
+
"vitest": "^4.1.10"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"homepage": "https://baychat.io",
|
|
23
|
+
"keywords": [
|
|
24
|
+
"baychat",
|
|
25
|
+
"agent",
|
|
26
|
+
"chat",
|
|
27
|
+
"claude-code",
|
|
28
|
+
"codex",
|
|
29
|
+
"cli",
|
|
30
|
+
"connector",
|
|
31
|
+
"group-chat"
|
|
32
|
+
],
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
]
|
|
38
|
+
}
|