@nopeek/agent-bridge 0.7.2 → 0.7.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/dist/bot.d.ts +5 -0
- package/dist/bot.js +34 -1
- package/dist/bridge.d.ts +1 -1
- package/dist/bridge.js +1 -1
- package/package.json +1 -1
package/dist/bot.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export declare class BotRunner {
|
|
|
25
25
|
private channelCache;
|
|
26
26
|
private allowed;
|
|
27
27
|
private accessLoaded;
|
|
28
|
+
private dmAllowed;
|
|
29
|
+
private mutedDmPrivate;
|
|
28
30
|
private declined;
|
|
29
31
|
private ownerPresence;
|
|
30
32
|
private mutedNoOwner;
|
|
@@ -50,6 +52,9 @@ export declare class BotRunner {
|
|
|
50
52
|
refreshAccess(): Promise<void>;
|
|
51
53
|
/** Sender permitted to talk to this bot? Fail closed if access never loaded. */
|
|
52
54
|
private isAllowed;
|
|
55
|
+
/** Sender permitted to DM this bot? Server-provided dmAllowedUserIds when we
|
|
56
|
+
* have it; otherwise (older backend) accountable owner + nominal owner. */
|
|
57
|
+
private isDmAllowed;
|
|
53
58
|
/** Merge live per-channel reply-mode updates (from a bot_config_changed
|
|
54
59
|
* control frame). Additive: only the listed channels change. */
|
|
55
60
|
applyChannelModes(modes: Record<string, ChannelMode>): void;
|
package/dist/bot.js
CHANGED
|
@@ -32,6 +32,14 @@ export class BotRunner {
|
|
|
32
32
|
// brain — so a stranger who finds the @handle can't drive the owner's agent.
|
|
33
33
|
allowed = new Set();
|
|
34
34
|
accessLoaded = false;
|
|
35
|
+
// DM PRIVACY: DMs with a bot are OWNER-ONLY unless the owner explicitly
|
|
36
|
+
// granted DM access. `dmAllowed` mirrors the server's dmAllowedUserIds
|
|
37
|
+
// (accountable owner + any explicit DM grants); null = the server didn't
|
|
38
|
+
// send the field (older backend) → fall back to accountable owner +
|
|
39
|
+
// info.ownerId. Enforced in kind=direct channels only — this also covers
|
|
40
|
+
// PRE-EXISTING DMs a non-owner opened before the server-side create guard.
|
|
41
|
+
dmAllowed = null;
|
|
42
|
+
mutedDmPrivate = new Set(); // DM channels already logged as owner-only
|
|
35
43
|
declined = new Set(); // (senderId) already told "not authorized" once
|
|
36
44
|
// OWNER-PRESENT POLICY (multi-party channels): other users may interact with
|
|
37
45
|
// the bot in a group ONLY while the bot's owner is ALSO a member of that
|
|
@@ -118,6 +126,7 @@ export class BotRunner {
|
|
|
118
126
|
throw new Error(`access HTTP ${res.status}`);
|
|
119
127
|
const j = (await res.json());
|
|
120
128
|
this.allowed = new Set(j.allowedUserIds ?? []);
|
|
129
|
+
this.dmAllowed = Array.isArray(j.dmAllowedUserIds) ? new Set(j.dmAllowedUserIds) : null;
|
|
121
130
|
// Channel reply modes: the access response is a full snapshot — replace
|
|
122
131
|
// the map (a channel the server no longer lists reverts to "everyone").
|
|
123
132
|
const modes = new Map();
|
|
@@ -150,6 +159,15 @@ export class BotRunner {
|
|
|
150
159
|
return false; // fail closed until we know the list
|
|
151
160
|
return this.allowed.has(senderUserId);
|
|
152
161
|
}
|
|
162
|
+
/** Sender permitted to DM this bot? Server-provided dmAllowedUserIds when we
|
|
163
|
+
* have it; otherwise (older backend) accountable owner + nominal owner. */
|
|
164
|
+
isDmAllowed(senderUserId) {
|
|
165
|
+
if (this.dmAllowed)
|
|
166
|
+
return this.dmAllowed.has(senderUserId);
|
|
167
|
+
return (senderUserId === this.effectiveOwnerId() ||
|
|
168
|
+
senderUserId === this.info.ownerId ||
|
|
169
|
+
senderUserId === this.runtimeOwnerId);
|
|
170
|
+
}
|
|
153
171
|
/** Merge live per-channel reply-mode updates (from a bot_config_changed
|
|
154
172
|
* control frame). Additive: only the listed channels change. */
|
|
155
173
|
applyChannelModes(modes) {
|
|
@@ -391,7 +409,22 @@ export class BotRunner {
|
|
|
391
409
|
const effOwner = this.effectiveOwnerId();
|
|
392
410
|
if (m.senderUserId !== effOwner) {
|
|
393
411
|
const ch = await this.getChannel(m.channelId);
|
|
394
|
-
if (ch.record.kind
|
|
412
|
+
if (ch.record.kind === "direct" || ch.record.kind === "dm") {
|
|
413
|
+
// DM PRIVACY: DMs with a bot are OWNER-ONLY (plus explicit DM grants
|
|
414
|
+
// from dmAllowedUserIds). A non-listed sender gets SILENCE — no brain
|
|
415
|
+
// run, no decline notice — even in a DM channel that predates the
|
|
416
|
+
// server-side create guard. Groups are handled below.
|
|
417
|
+
if (!this.isDmAllowed(m.senderUserId)) {
|
|
418
|
+
if (!this.mutedDmPrivate.has(m.channelId)) {
|
|
419
|
+
this.mutedDmPrivate.add(m.channelId);
|
|
420
|
+
this.log(`muting DM ${m.channelId} — sender ${m.senderUserId} is not in dmAllowedUserIds (bot DMs are owner-only); staying silent`);
|
|
421
|
+
}
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
this.mutedDmPrivate.delete(m.channelId);
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
// OWNER-PRESENT POLICY (groups)
|
|
395
428
|
if (!(await this.ownerIsChannelMember(m.channelId))) {
|
|
396
429
|
if (!this.mutedNoOwner.has(m.channelId)) {
|
|
397
430
|
this.mutedNoOwner.add(m.channelId);
|
package/dist/bridge.d.ts
CHANGED
package/dist/bridge.js
CHANGED
|
@@ -17,7 +17,7 @@ import { resolveBrain } from "./brain.js";
|
|
|
17
17
|
import { provisionSoul, provisionHermesProfile } from "./backends.js";
|
|
18
18
|
import { reportCapabilities } from "./capabilities.js";
|
|
19
19
|
import { isBrainBackend } from "./config.js";
|
|
20
|
-
export const VERSION = "0.7.
|
|
20
|
+
export const VERSION = "0.7.4";
|
|
21
21
|
/** How often to re-probe + report brain availability to the server. */
|
|
22
22
|
const CAPABILITIES_INTERVAL_MS = 5 * 60_000;
|
|
23
23
|
export class PairError extends Error {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nopeek/agent-bridge",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Run your own agents as E2EE NoPeek bots. Pairs with one-time codes (multiple accounts per computer), runs every bot each account owns, and pipes messages to any command or webhook.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|