baychat 0.21.5 → 0.22.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 +53 -1
- package/dist/approve-hook.js +5 -2
- package/dist/commands.js +6 -4
- package/dist/connect-dsh.js +165 -0
- package/dist/connect-plan.js +16 -1
- package/dist/connect.js +7 -0
- package/dist/doctor-command.js +7 -0
- package/dist/doctor.js +94 -1
- package/dist/dsh-config.js +147 -0
- package/dist/index.js +22 -0
- package/dist/relay/acp/agents.js +186 -0
- package/dist/relay/acp/approval.js +67 -0
- package/dist/relay/acp/client.js +253 -0
- package/dist/relay/acp/commands.js +69 -0
- package/dist/relay/acp/daemon-glue.js +201 -0
- package/dist/relay/acp/dump-config.js +31 -0
- package/dist/relay/acp/modes.js +36 -0
- package/dist/relay/acp/permissions.js +42 -0
- package/dist/relay/acp/policy.js +137 -0
- package/dist/relay/acp/presence.js +87 -0
- package/dist/relay/acp/prompt.js +69 -0
- package/dist/relay/acp/runner.js +311 -0
- package/dist/relay/acp/sdk.js +19 -0
- package/dist/relay/acp/turn-queue.js +163 -0
- package/dist/relay/acp/types.js +2 -0
- package/dist/relay/commands.js +28 -0
- package/dist/relay/daemon.js +195 -0
- package/dist/relay/mailbox.js +1 -0
- package/dist/relay/profiles.js +22 -0
- package/dist/relay/registry.js +46 -1
- package/dist/relay/session-commands.js +89 -0
- package/dist/relay/session-reply.js +25 -0
- package/dist/relay/terminal-pane.js +197 -0
- package/dist/relay/types.js +0 -9
- package/dist/runtimes.js +13 -0
- package/dist/session-command.js +16 -3
- package/dist/skill-bootstrap.js +16 -8
- package/dist/start-command.js +235 -0
- package/dist/update-command.js +201 -0
- package/package.json +3 -1
|
@@ -0,0 +1,201 @@
|
|
|
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.cmdUpdate = cmdUpdate;
|
|
37
|
+
exports.autoUpdateDue = autoUpdateDue;
|
|
38
|
+
const child_process_1 = require("child_process");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const config_1 = require("./config");
|
|
42
|
+
const credential_refresh_1 = require("./credential-refresh");
|
|
43
|
+
const commands_1 = require("./commands");
|
|
44
|
+
const client_paths_1 = require("./client-paths");
|
|
45
|
+
const commands_2 = require("./relay/commands");
|
|
46
|
+
/**
|
|
47
|
+
* `baychat update` — bring this whole machine onto the current version, in one word.
|
|
48
|
+
*
|
|
49
|
+
* ── THE PROBLEM IT EXISTS TO END ──────────────────────────────────────────────────────
|
|
50
|
+
*
|
|
51
|
+
* Karmen, 2026-09-14: *"it's not every time when we make an update the person has to
|
|
52
|
+
* update three different things from two different terminals… I just want it to be like
|
|
53
|
+
* `baychat update` and everything reloads."*
|
|
54
|
+
*
|
|
55
|
+
* She is describing something this project has been bitten by repeatedly. Shipping a CLI
|
|
56
|
+
* change reaches NOBODY until, on every machine: the package is refetched, each connected
|
|
57
|
+
* client's MCP config is rewritten, and **the relay daemon is restarted** — a live daemon
|
|
58
|
+
* holds the old code in memory and will happily keep running it for weeks. Three steps, in
|
|
59
|
+
* different places, none of them discoverable, and the failure is silence rather than an
|
|
60
|
+
* error.
|
|
61
|
+
*
|
|
62
|
+
* ── IT REFRESHES WHAT IS ALREADY THERE, AND CONNECTS NOTHING NEW ──────────────────────
|
|
63
|
+
*
|
|
64
|
+
* Every step is idempotent and every step is a RE-application of a decision the person
|
|
65
|
+
* already made. `refreshExistingClientConfigs` only rewrites config files that already
|
|
66
|
+
* name BayChat; Claude Code is only re-registered if its binary is present; Hermes only if
|
|
67
|
+
* `~/.hermes` exists. Running this on a machine that has never been connected does
|
|
68
|
+
* nothing, loudly — which is the right answer, because "update" must never quietly become
|
|
69
|
+
* "set up", and a command that installed things would not be safe to run automatically.
|
|
70
|
+
*
|
|
71
|
+
* And it must be safe to run automatically, because that is the second half of her ask:
|
|
72
|
+
* `baychat start` calls this on a day-boundary so nobody has to remember it at all.
|
|
73
|
+
*/
|
|
74
|
+
/** How often `start` re-checks, when it is driving. One a day is invisible; one an hour is a tax. */
|
|
75
|
+
const AUTO_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
76
|
+
const STAMP_FILE = "last-update-check.json";
|
|
77
|
+
async function cmdUpdate(opts = {}) {
|
|
78
|
+
const say = (line) => {
|
|
79
|
+
if (!opts.quiet)
|
|
80
|
+
console.log(line);
|
|
81
|
+
};
|
|
82
|
+
const device = (0, config_1.loadDeviceCredentials)();
|
|
83
|
+
if (!device) {
|
|
84
|
+
console.error("This machine is not signed in, so there is nothing to update. Run `npx baychat login` first.");
|
|
85
|
+
return 1;
|
|
86
|
+
}
|
|
87
|
+
const done = [];
|
|
88
|
+
// 1. THE PACKAGE. Only a global install can be upgraded in place; an npx run already
|
|
89
|
+
// fetched whatever npx had cached, and the honest advice there is `@latest`.
|
|
90
|
+
const packageStep = updatePackage();
|
|
91
|
+
if (packageStep)
|
|
92
|
+
done.push(packageStep);
|
|
93
|
+
// 2. EVERY CONNECTED CLIENT's copy of the credential and endpoint.
|
|
94
|
+
try {
|
|
95
|
+
const updated = (0, credential_refresh_1.refreshExistingClientConfigs)({ url: `${device.baseUrl}/api/mcp`, token: device.token }, commands_1.realConfigIo, (0, client_paths_1.currentPathEnv)());
|
|
96
|
+
for (const file of updated)
|
|
97
|
+
done.push(`refreshed ${file}`);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
// Never fatal: the next steps are independent, and a machine that failed one of four
|
|
101
|
+
// is better off doing the other three than stopping at the first.
|
|
102
|
+
say(` Could not refresh client configs: ${errText(err)}`);
|
|
103
|
+
}
|
|
104
|
+
// 3. CLAUDE CODE, which is not an MCP-config client and registers through its own CLI.
|
|
105
|
+
if (hasBinary("claude") && (0, commands_1.registerWithClaude)(device.baseUrl, device.token)) {
|
|
106
|
+
done.push("re-registered BayChat with Claude Code");
|
|
107
|
+
}
|
|
108
|
+
// 4. THE RELAY — the step people forget, and the one that silently keeps old code
|
|
109
|
+
// running. Stopped and started rather than signalled: the daemon loads its code at
|
|
110
|
+
// process start, so nothing short of a restart picks up a new version.
|
|
111
|
+
try {
|
|
112
|
+
await (0, commands_2.cmdRelayStop)();
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Not running is the normal case on a fresh boot, and is not a failure to report.
|
|
116
|
+
}
|
|
117
|
+
const relay = await (0, commands_2.ensureRelayInstalled)();
|
|
118
|
+
done.push(relay.startsWith("Relay:") ? relay.toLowerCase() : relay);
|
|
119
|
+
writeStamp();
|
|
120
|
+
if (done.length === 0) {
|
|
121
|
+
say("Everything was already up to date.");
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
if (opts.quiet) {
|
|
125
|
+
// Driven by `start`: one line, because the person asked to begin work, not to read a
|
|
126
|
+
// report. The full account is available by running the command by hand.
|
|
127
|
+
console.log(`BayChat updated (${done.length} step${done.length === 1 ? "" : "s"}).`);
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
console.log("Updated this machine:");
|
|
131
|
+
for (const line of done)
|
|
132
|
+
console.log(` ✓ ${line}`);
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Has it been long enough for `start` to check again?
|
|
137
|
+
*
|
|
138
|
+
* A stamp rather than a version comparison: the point is to bound how often the network is
|
|
139
|
+
* touched on a path whose whole job is to start work quickly.
|
|
140
|
+
*/
|
|
141
|
+
function autoUpdateDue(now = Date.now()) {
|
|
142
|
+
try {
|
|
143
|
+
const raw = JSON.parse(fs.readFileSync(stampPath(), "utf8"));
|
|
144
|
+
if (typeof raw.at !== "number")
|
|
145
|
+
return true;
|
|
146
|
+
return now - raw.at >= AUTO_CHECK_INTERVAL_MS;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// Never checked, or unreadable — checking is the safe answer.
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function stampPath() {
|
|
154
|
+
return path.join((0, config_1.configDir)(), STAMP_FILE);
|
|
155
|
+
}
|
|
156
|
+
function writeStamp() {
|
|
157
|
+
try {
|
|
158
|
+
fs.mkdirSync((0, config_1.configDir)(), { recursive: true });
|
|
159
|
+
fs.writeFileSync(stampPath(), JSON.stringify({ at: Date.now() }));
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Costs one extra check tomorrow. Never worth failing an update for.
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Upgrade the package itself, where that is a thing this process can do.
|
|
167
|
+
*
|
|
168
|
+
* ⚠️ AN `npx` RUN CANNOT UPGRADE ITSELF, and pretending otherwise is worse than saying so:
|
|
169
|
+
* npx resolves from its own cache, so `npx baychat` can keep running a version from weeks
|
|
170
|
+
* ago while reporting success at every step. The honest output there is the one flag that
|
|
171
|
+
* fixes it.
|
|
172
|
+
*/
|
|
173
|
+
function updatePackage() {
|
|
174
|
+
const globalInstall = isGlobalInstall();
|
|
175
|
+
if (!globalInstall) {
|
|
176
|
+
console.log("Tip: `npx baychat` can run a cached older copy. Use `npx baychat@latest` (or install it once with `npm i -g baychat`) so updates land.");
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
const result = (0, child_process_1.spawnSync)("npm", ["install", "-g", "baychat@latest"], {
|
|
180
|
+
encoding: "utf8",
|
|
181
|
+
timeout: 120_000,
|
|
182
|
+
});
|
|
183
|
+
if (result.status !== 0) {
|
|
184
|
+
console.log(` Could not upgrade the package: ${result.stderr?.trim() || "npm failed"}`);
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
return "upgraded the baychat package";
|
|
188
|
+
}
|
|
189
|
+
/** Is this process running from a global npm install, rather than an npx cache? */
|
|
190
|
+
function isGlobalInstall() {
|
|
191
|
+
const self = process.argv[1] ?? "";
|
|
192
|
+
// npx unpacks into `_npx` inside the npm cache; a global install never does.
|
|
193
|
+
return self.includes("node_modules") && !self.includes("_npx");
|
|
194
|
+
}
|
|
195
|
+
function hasBinary(name) {
|
|
196
|
+
const probe = (0, child_process_1.spawnSync)(name, ["--version"], { stdio: "ignore", timeout: 15_000 });
|
|
197
|
+
return !probe.error && probe.status === 0;
|
|
198
|
+
}
|
|
199
|
+
function errText(err) {
|
|
200
|
+
return err instanceof Error ? err.message : String(err);
|
|
201
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "baychat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "BayChat connector CLI — pair an agent session (Claude Code, Codex) with BayChat and chat in groups",
|
|
5
5
|
"bin": {
|
|
6
6
|
"baychat": "dist/index.js"
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"sync-protocol": "node scripts/sync-protocol.mjs",
|
|
14
14
|
"build": "node scripts/sync-protocol.mjs && node scripts/sync-hermes-plugin.mjs && tsc && node scripts/make-executable.mjs",
|
|
15
15
|
"test": "vitest run",
|
|
16
|
+
"test:contract": "vitest run src/relay/acp/contract.test.ts",
|
|
16
17
|
"prepublishOnly": "npm run build && npm test"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
"LICENSE"
|
|
39
40
|
],
|
|
40
41
|
"dependencies": {
|
|
42
|
+
"@agentclientprotocol/sdk": "1.4.0",
|
|
41
43
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
42
44
|
"qrcode": "^1.5.4",
|
|
43
45
|
"yaml": "^2.9.0",
|