@spinabot/brigade 1.7.0 → 1.9.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 +19 -0
- package/dist/agents/agent-loop.d.ts +13 -0
- package/dist/agents/agent-loop.d.ts.map +1 -1
- package/dist/agents/agent-loop.js +5 -0
- package/dist/agents/agent-loop.js.map +1 -1
- package/dist/agents/channels/access-control/group-tool-policy.d.ts +73 -0
- package/dist/agents/channels/access-control/group-tool-policy.d.ts.map +1 -0
- package/dist/agents/channels/access-control/group-tool-policy.js +193 -0
- package/dist/agents/channels/access-control/group-tool-policy.js.map +1 -0
- package/dist/agents/channels/access-control/index.d.ts +1 -0
- package/dist/agents/channels/access-control/index.d.ts.map +1 -1
- package/dist/agents/channels/access-control/index.js +1 -0
- package/dist/agents/channels/access-control/index.js.map +1 -1
- package/dist/agents/channels/bluebubbles/account-config.d.ts +253 -0
- package/dist/agents/channels/bluebubbles/account-config.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/account-config.js +486 -0
- package/dist/agents/channels/bluebubbles/account-config.js.map +1 -0
- package/dist/agents/channels/bluebubbles/account-registry.d.ts +33 -0
- package/dist/agents/channels/bluebubbles/account-registry.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/account-registry.js +46 -0
- package/dist/agents/channels/bluebubbles/account-registry.js.map +1 -0
- package/dist/agents/channels/bluebubbles/adapter.d.ts +45 -0
- package/dist/agents/channels/bluebubbles/adapter.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/adapter.js +366 -0
- package/dist/agents/channels/bluebubbles/adapter.js.map +1 -0
- package/dist/agents/channels/bluebubbles/catchup-cursor.d.ts +52 -0
- package/dist/agents/channels/bluebubbles/catchup-cursor.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/catchup-cursor.js +118 -0
- package/dist/agents/channels/bluebubbles/catchup-cursor.js.map +1 -0
- package/dist/agents/channels/bluebubbles/catchup.d.ts +114 -0
- package/dist/agents/channels/bluebubbles/catchup.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/catchup.js +220 -0
- package/dist/agents/channels/bluebubbles/catchup.js.map +1 -0
- package/dist/agents/channels/bluebubbles/chat.d.ts +75 -0
- package/dist/agents/channels/bluebubbles/chat.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/chat.js +182 -0
- package/dist/agents/channels/bluebubbles/chat.js.map +1 -0
- package/dist/agents/channels/bluebubbles/connection.d.ts +95 -0
- package/dist/agents/channels/bluebubbles/connection.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/connection.js +413 -0
- package/dist/agents/channels/bluebubbles/connection.js.map +1 -0
- package/dist/agents/channels/bluebubbles/contact-names.d.ts +79 -0
- package/dist/agents/channels/bluebubbles/contact-names.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/contact-names.js +188 -0
- package/dist/agents/channels/bluebubbles/contact-names.js.map +1 -0
- package/dist/agents/channels/bluebubbles/debounce.d.ts +78 -0
- package/dist/agents/channels/bluebubbles/debounce.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/debounce.js +173 -0
- package/dist/agents/channels/bluebubbles/debounce.js.map +1 -0
- package/dist/agents/channels/bluebubbles/dedupe.d.ts +25 -0
- package/dist/agents/channels/bluebubbles/dedupe.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/dedupe.js +35 -0
- package/dist/agents/channels/bluebubbles/dedupe.js.map +1 -0
- package/dist/agents/channels/bluebubbles/effects.d.ts +17 -0
- package/dist/agents/channels/bluebubbles/effects.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/effects.js +57 -0
- package/dist/agents/channels/bluebubbles/effects.js.map +1 -0
- package/dist/agents/channels/bluebubbles/history.d.ts +56 -0
- package/dist/agents/channels/bluebubbles/history.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/history.js +140 -0
- package/dist/agents/channels/bluebubbles/history.js.map +1 -0
- package/dist/agents/channels/bluebubbles/index.d.ts +18 -0
- package/dist/agents/channels/bluebubbles/index.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/index.js +18 -0
- package/dist/agents/channels/bluebubbles/index.js.map +1 -0
- package/dist/agents/channels/bluebubbles/media.d.ts +104 -0
- package/dist/agents/channels/bluebubbles/media.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/media.js +222 -0
- package/dist/agents/channels/bluebubbles/media.js.map +1 -0
- package/dist/agents/channels/bluebubbles/messaging.d.ts +13 -0
- package/dist/agents/channels/bluebubbles/messaging.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/messaging.js +36 -0
- package/dist/agents/channels/bluebubbles/messaging.js.map +1 -0
- package/dist/agents/channels/bluebubbles/module.d.ts +24 -0
- package/dist/agents/channels/bluebubbles/module.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/module.js +52 -0
- package/dist/agents/channels/bluebubbles/module.js.map +1 -0
- package/dist/agents/channels/bluebubbles/normalize.d.ts +111 -0
- package/dist/agents/channels/bluebubbles/normalize.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/normalize.js +239 -0
- package/dist/agents/channels/bluebubbles/normalize.js.map +1 -0
- package/dist/agents/channels/bluebubbles/plugin.d.ts +46 -0
- package/dist/agents/channels/bluebubbles/plugin.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/plugin.js +242 -0
- package/dist/agents/channels/bluebubbles/plugin.js.map +1 -0
- package/dist/agents/channels/bluebubbles/probe.d.ts +79 -0
- package/dist/agents/channels/bluebubbles/probe.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/probe.js +138 -0
- package/dist/agents/channels/bluebubbles/probe.js.map +1 -0
- package/dist/agents/channels/bluebubbles/reactions.d.ts +46 -0
- package/dist/agents/channels/bluebubbles/reactions.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/reactions.js +207 -0
- package/dist/agents/channels/bluebubbles/reactions.js.map +1 -0
- package/dist/agents/channels/bluebubbles/send.d.ts +132 -0
- package/dist/agents/channels/bluebubbles/send.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/send.js +327 -0
- package/dist/agents/channels/bluebubbles/send.js.map +1 -0
- package/dist/agents/channels/bluebubbles/status-issues.d.ts +57 -0
- package/dist/agents/channels/bluebubbles/status-issues.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/status-issues.js +93 -0
- package/dist/agents/channels/bluebubbles/status-issues.js.map +1 -0
- package/dist/agents/channels/bluebubbles/types.d.ts +69 -0
- package/dist/agents/channels/bluebubbles/types.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/types.js +118 -0
- package/dist/agents/channels/bluebubbles/types.js.map +1 -0
- package/dist/agents/channels/bluebubbles/webhook.d.ts +97 -0
- package/dist/agents/channels/bluebubbles/webhook.d.ts.map +1 -0
- package/dist/agents/channels/bluebubbles/webhook.js +249 -0
- package/dist/agents/channels/bluebubbles/webhook.js.map +1 -0
- package/dist/agents/channels/bundled-channel-metas.d.ts +13 -0
- package/dist/agents/channels/bundled-channel-metas.d.ts.map +1 -1
- package/dist/agents/channels/bundled-channel-metas.js +33 -0
- package/dist/agents/channels/bundled-channel-metas.js.map +1 -1
- package/dist/agents/channels/imessage/account-config.d.ts +178 -0
- package/dist/agents/channels/imessage/account-config.d.ts.map +1 -0
- package/dist/agents/channels/imessage/account-config.js +371 -0
- package/dist/agents/channels/imessage/account-config.js.map +1 -0
- package/dist/agents/channels/imessage/adapter.d.ts +36 -0
- package/dist/agents/channels/imessage/adapter.d.ts.map +1 -0
- package/dist/agents/channels/imessage/adapter.js +286 -0
- package/dist/agents/channels/imessage/adapter.js.map +1 -0
- package/dist/agents/channels/imessage/client.d.ts +99 -0
- package/dist/agents/channels/imessage/client.d.ts.map +1 -0
- package/dist/agents/channels/imessage/client.js +231 -0
- package/dist/agents/channels/imessage/client.js.map +1 -0
- package/dist/agents/channels/imessage/connection.d.ts +101 -0
- package/dist/agents/channels/imessage/connection.d.ts.map +1 -0
- package/dist/agents/channels/imessage/connection.js +367 -0
- package/dist/agents/channels/imessage/connection.js.map +1 -0
- package/dist/agents/channels/imessage/format.d.ts +45 -0
- package/dist/agents/channels/imessage/format.d.ts.map +1 -0
- package/dist/agents/channels/imessage/format.js +170 -0
- package/dist/agents/channels/imessage/format.js.map +1 -0
- package/dist/agents/channels/imessage/history.d.ts +49 -0
- package/dist/agents/channels/imessage/history.d.ts.map +1 -0
- package/dist/agents/channels/imessage/history.js +74 -0
- package/dist/agents/channels/imessage/history.js.map +1 -0
- package/dist/agents/channels/imessage/index.d.ts +25 -0
- package/dist/agents/channels/imessage/index.d.ts.map +1 -0
- package/dist/agents/channels/imessage/index.js +25 -0
- package/dist/agents/channels/imessage/index.js.map +1 -0
- package/dist/agents/channels/imessage/media.d.ts +92 -0
- package/dist/agents/channels/imessage/media.d.ts.map +1 -0
- package/dist/agents/channels/imessage/media.js +196 -0
- package/dist/agents/channels/imessage/media.js.map +1 -0
- package/dist/agents/channels/imessage/messaging.d.ts +14 -0
- package/dist/agents/channels/imessage/messaging.d.ts.map +1 -0
- package/dist/agents/channels/imessage/messaging.js +37 -0
- package/dist/agents/channels/imessage/messaging.js.map +1 -0
- package/dist/agents/channels/imessage/module.d.ts +16 -0
- package/dist/agents/channels/imessage/module.d.ts.map +1 -0
- package/dist/agents/channels/imessage/module.js +23 -0
- package/dist/agents/channels/imessage/module.js.map +1 -0
- package/dist/agents/channels/imessage/monitor.d.ts +207 -0
- package/dist/agents/channels/imessage/monitor.d.ts.map +1 -0
- package/dist/agents/channels/imessage/monitor.js +504 -0
- package/dist/agents/channels/imessage/monitor.js.map +1 -0
- package/dist/agents/channels/imessage/plugin.d.ts +53 -0
- package/dist/agents/channels/imessage/plugin.d.ts.map +1 -0
- package/dist/agents/channels/imessage/plugin.js +215 -0
- package/dist/agents/channels/imessage/plugin.js.map +1 -0
- package/dist/agents/channels/imessage/probe.d.ts +68 -0
- package/dist/agents/channels/imessage/probe.d.ts.map +1 -0
- package/dist/agents/channels/imessage/probe.js +134 -0
- package/dist/agents/channels/imessage/probe.js.map +1 -0
- package/dist/agents/channels/imessage/remote-attachments.d.ts +61 -0
- package/dist/agents/channels/imessage/remote-attachments.d.ts.map +1 -0
- package/dist/agents/channels/imessage/remote-attachments.js +131 -0
- package/dist/agents/channels/imessage/remote-attachments.js.map +1 -0
- package/dist/agents/channels/imessage/send.d.ts +61 -0
- package/dist/agents/channels/imessage/send.d.ts.map +1 -0
- package/dist/agents/channels/imessage/send.js +108 -0
- package/dist/agents/channels/imessage/send.js.map +1 -0
- package/dist/agents/channels/imessage/targets.d.ts +91 -0
- package/dist/agents/channels/imessage/targets.d.ts.map +1 -0
- package/dist/agents/channels/imessage/targets.js +245 -0
- package/dist/agents/channels/imessage/targets.js.map +1 -0
- package/dist/agents/channels/imessage/watch-error.d.ts +23 -0
- package/dist/agents/channels/imessage/watch-error.d.ts.map +1 -0
- package/dist/agents/channels/imessage/watch-error.js +69 -0
- package/dist/agents/channels/imessage/watch-error.js.map +1 -0
- package/dist/agents/channels/inbound-pipeline.d.ts +11 -0
- package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
- package/dist/agents/channels/inbound-pipeline.js +20 -1
- package/dist/agents/channels/inbound-pipeline.js.map +1 -1
- package/dist/agents/channels/manager.d.ts +9 -0
- package/dist/agents/channels/manager.d.ts.map +1 -1
- package/dist/agents/channels/manager.js.map +1 -1
- package/dist/agents/channels/sdk.d.ts +4 -0
- package/dist/agents/channels/sdk.d.ts.map +1 -1
- package/dist/agents/channels/sdk.js +4 -0
- package/dist/agents/channels/sdk.js.map +1 -1
- package/dist/agents/extensions/modules/index.d.ts.map +1 -1
- package/dist/agents/extensions/modules/index.js +12 -0
- package/dist/agents/extensions/modules/index.js.map +1 -1
- package/dist/agents/session-wiring.d.ts +31 -0
- package/dist/agents/session-wiring.d.ts.map +1 -1
- package/dist/agents/session-wiring.js +45 -2
- package/dist/agents/session-wiring.js.map +1 -1
- package/dist/agents/tools/bluebubbles-action-tool.d.ts +66 -0
- package/dist/agents/tools/bluebubbles-action-tool.d.ts.map +1 -0
- package/dist/agents/tools/bluebubbles-action-tool.js +234 -0
- package/dist/agents/tools/bluebubbles-action-tool.js.map +1 -0
- package/dist/agents/tools/registry.d.ts.map +1 -1
- package/dist/agents/tools/registry.js +18 -0
- package/dist/agents/tools/registry.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/cli/commands/expose.d.ts +40 -0
- package/dist/cli/commands/expose.d.ts.map +1 -0
- package/dist/cli/commands/expose.js +200 -0
- package/dist/cli/commands/expose.js.map +1 -0
- package/dist/cli/program/build-program.d.ts.map +1 -1
- package/dist/cli/program/build-program.js +61 -0
- package/dist/cli/program/build-program.js.map +1 -1
- package/dist/config/io.d.ts +41 -0
- package/dist/config/io.d.ts.map +1 -1
- package/dist/config/io.js.map +1 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +48 -2
- package/dist/core/server.js.map +1 -1
- package/dist/core/tunnel/auth-proxy.d.ts +55 -0
- package/dist/core/tunnel/auth-proxy.d.ts.map +1 -0
- package/dist/core/tunnel/auth-proxy.js +179 -0
- package/dist/core/tunnel/auth-proxy.js.map +1 -0
- package/dist/core/tunnel/manager.d.ts +42 -0
- package/dist/core/tunnel/manager.d.ts.map +1 -0
- package/dist/core/tunnel/manager.js +102 -0
- package/dist/core/tunnel/manager.js.map +1 -0
- package/dist/core/tunnel/providers/bore.d.ts +18 -0
- package/dist/core/tunnel/providers/bore.d.ts.map +1 -0
- package/dist/core/tunnel/providers/bore.js +117 -0
- package/dist/core/tunnel/providers/bore.js.map +1 -0
- package/dist/core/tunnel/providers/cloudflared.d.ts +24 -0
- package/dist/core/tunnel/providers/cloudflared.d.ts.map +1 -0
- package/dist/core/tunnel/providers/cloudflared.js +179 -0
- package/dist/core/tunnel/providers/cloudflared.js.map +1 -0
- package/dist/core/tunnel/providers/custom.d.ts +21 -0
- package/dist/core/tunnel/providers/custom.d.ts.map +1 -0
- package/dist/core/tunnel/providers/custom.js +124 -0
- package/dist/core/tunnel/providers/custom.js.map +1 -0
- package/dist/core/tunnel/registry.d.ts +15 -0
- package/dist/core/tunnel/registry.d.ts.map +1 -0
- package/dist/core/tunnel/registry.js +26 -0
- package/dist/core/tunnel/registry.js.map +1 -0
- package/dist/core/tunnel/state.d.ts +39 -0
- package/dist/core/tunnel/state.d.ts.map +1 -0
- package/dist/core/tunnel/state.js +57 -0
- package/dist/core/tunnel/state.js.map +1 -0
- package/dist/core/tunnel/types.d.ts +61 -0
- package/dist/core/tunnel/types.d.ts.map +1 -0
- package/dist/core/tunnel/types.js +20 -0
- package/dist/core/tunnel/types.js.map +1 -0
- package/dist/infra/net/fetch-guard.d.ts +24 -2
- package/dist/infra/net/fetch-guard.d.ts.map +1 -1
- package/dist/infra/net/fetch-guard.js +78 -31
- package/dist/infra/net/fetch-guard.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage media helpers — outbound attachment resolution + inbound kind
|
|
3
|
+
* inference.
|
|
4
|
+
*
|
|
5
|
+
* OUTBOUND: the `imsg` bridge sends an attachment by LOCAL PATH (the `file` RPC
|
|
6
|
+
* param), so there is no upload step — we just validate the local path through
|
|
7
|
+
* Brigade's outbound media-path guard (so a prompt-injected "send ~/.ssh/id_rsa"
|
|
8
|
+
* can't exfiltrate a secret) and enforce the per-account size cap. The resolved
|
|
9
|
+
* `{ path, kind, mimeType }` is what `send.ts` hands the RPC.
|
|
10
|
+
*
|
|
11
|
+
* INBOUND: the bridge has ALREADY saved received attachments to disk under the
|
|
12
|
+
* macOS Messages Attachments dir (the `attachmentRoots` allow-list). We don't
|
|
13
|
+
* fetch anything — we just map the bridge's reported `mime_type` to a Brigade
|
|
14
|
+
* media `kind` and surface the on-disk `path` so the agent can `read` it. The
|
|
15
|
+
* path is checked against the configured attachment roots so a malicious bridge
|
|
16
|
+
* payload can't point Brigade at an arbitrary file.
|
|
17
|
+
*/
|
|
18
|
+
import { statSync } from "node:fs";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
// Channel SDK barrel — the outbound-media exfil guard + the contract types. All
|
|
21
|
+
// contract types come from the channel SDK barrel so the channel is built
|
|
22
|
+
// entirely on `../sdk.js`.
|
|
23
|
+
import { validateOutboundMediaPath } from "../sdk.js";
|
|
24
|
+
import { scpCopyRemoteAttachment } from "./remote-attachments.js";
|
|
25
|
+
/** Map a MIME type to a Brigade media kind (defaults to `document`). */
|
|
26
|
+
export function kindFromMime(mime) {
|
|
27
|
+
const m = (mime ?? "").trim().toLowerCase();
|
|
28
|
+
if (m.startsWith("image/"))
|
|
29
|
+
return "image";
|
|
30
|
+
if (m.startsWith("video/"))
|
|
31
|
+
return "video";
|
|
32
|
+
if (m.startsWith("audio/"))
|
|
33
|
+
return "audio";
|
|
34
|
+
return "document";
|
|
35
|
+
}
|
|
36
|
+
/** Map a file extension to a Brigade media kind (defaults to `document`). */
|
|
37
|
+
export function kindFromExt(filePath) {
|
|
38
|
+
const ext = path.extname(filePath).toLowerCase().replace(/^\./, "");
|
|
39
|
+
if (["png", "jpg", "jpeg", "gif", "webp", "heic", "bmp", "tiff"].includes(ext))
|
|
40
|
+
return "image";
|
|
41
|
+
if (["mp4", "mov", "m4v", "webm", "avi", "mkv"].includes(ext))
|
|
42
|
+
return "video";
|
|
43
|
+
if (["mp3", "m4a", "aac", "wav", "ogg", "flac", "caf", "amr"].includes(ext))
|
|
44
|
+
return "audio";
|
|
45
|
+
return "document";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve an outbound media path for the send RPC: run the exfil guard, enforce
|
|
49
|
+
* the size cap, and infer the kind. Throws an operator-facing error when the
|
|
50
|
+
* path is refused or too large.
|
|
51
|
+
*/
|
|
52
|
+
export function resolveOutboundAttachment(rawPath, maxBytes) {
|
|
53
|
+
const filePath = (rawPath ?? "").trim();
|
|
54
|
+
if (!filePath)
|
|
55
|
+
throw new Error("iMessage media path is required");
|
|
56
|
+
const verdict = validateOutboundMediaPath(filePath);
|
|
57
|
+
if (!verdict.ok) {
|
|
58
|
+
throw new Error(`iMessage refused to attach "${filePath}": ${verdict.reason}`);
|
|
59
|
+
}
|
|
60
|
+
const resolved = path.resolve(filePath);
|
|
61
|
+
let size = 0;
|
|
62
|
+
try {
|
|
63
|
+
size = statSync(resolved).size;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
throw new Error(`iMessage media path not found: ${resolved}`);
|
|
67
|
+
}
|
|
68
|
+
if (maxBytes > 0 && size > maxBytes) {
|
|
69
|
+
const mb = (maxBytes / (1024 * 1024)).toFixed(0);
|
|
70
|
+
throw new Error(`iMessage media is too large (${(size / (1024 * 1024)).toFixed(1)} MB > ${mb} MB cap)`);
|
|
71
|
+
}
|
|
72
|
+
return { path: resolved, kind: kindFromExt(resolved) };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Build an OutboundMedia descriptor's `kind` for a path (used when the caller
|
|
76
|
+
* already validated the path). Mirrors `kindFromExt` but kept as a named export
|
|
77
|
+
* so callers read clearly.
|
|
78
|
+
*/
|
|
79
|
+
export function inferOutboundMediaKind(media) {
|
|
80
|
+
if (media.kind)
|
|
81
|
+
return media.kind;
|
|
82
|
+
return kindFromExt(media.path);
|
|
83
|
+
}
|
|
84
|
+
/** Normalise a path's separators to `/` for cross-platform root comparison. */
|
|
85
|
+
function toPosixish(p) {
|
|
86
|
+
return p.replace(/\\/g, "/");
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* True when a resolved on-disk path lives under one of the allowed roots.
|
|
90
|
+
*
|
|
91
|
+
* Roots are POSIX-style macOS paths (the bridge reports paths from a Mac), so
|
|
92
|
+
* matching is done on forward-slash-normalised strings — NOT `path.resolve`,
|
|
93
|
+
* which on Windows would drive-root a leading-slash path and flip the separators
|
|
94
|
+
* (breaking the glob-tail check). A wildcard segment in a root (e.g. the user
|
|
95
|
+
* segment in /Users/<wildcard>/Library/Messages/Attachments) matches any single
|
|
96
|
+
* path segment.
|
|
97
|
+
*/
|
|
98
|
+
export function isUnderAllowedRoot(filePath, roots) {
|
|
99
|
+
const target = toPosixish((filePath ?? "").trim());
|
|
100
|
+
if (!target)
|
|
101
|
+
return false;
|
|
102
|
+
const targetSegs = target.split("/").filter(Boolean);
|
|
103
|
+
for (const root of roots) {
|
|
104
|
+
const r = toPosixish(root.trim());
|
|
105
|
+
if (!r)
|
|
106
|
+
continue;
|
|
107
|
+
const rootSegs = r.split("/").filter(Boolean);
|
|
108
|
+
if (rootSegs.length === 0 || targetSegs.length < rootSegs.length)
|
|
109
|
+
continue;
|
|
110
|
+
let matched = true;
|
|
111
|
+
for (let i = 0; i < rootSegs.length; i++) {
|
|
112
|
+
if (rootSegs[i] === "*")
|
|
113
|
+
continue;
|
|
114
|
+
if (rootSegs[i] !== targetSegs[i]) {
|
|
115
|
+
matched = false;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (matched)
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Map the bridge's reported inbound attachments to Brigade `InboundMediaAttachment`s,
|
|
126
|
+
* dropping any that are missing or whose on-disk path falls outside the allowed
|
|
127
|
+
* roots. Returns [] when nothing resolved.
|
|
128
|
+
*/
|
|
129
|
+
export function resolveInboundAttachments(raw, allowedRoots) {
|
|
130
|
+
if (!Array.isArray(raw))
|
|
131
|
+
return [];
|
|
132
|
+
const out = [];
|
|
133
|
+
for (const att of raw) {
|
|
134
|
+
if (!att || att.missing === true)
|
|
135
|
+
continue;
|
|
136
|
+
const p = (att.original_path ?? "").trim();
|
|
137
|
+
if (!p)
|
|
138
|
+
continue;
|
|
139
|
+
if (allowedRoots.length > 0 && !isUnderAllowedRoot(p, allowedRoots))
|
|
140
|
+
continue;
|
|
141
|
+
const mimeType = (att.mime_type ?? "").trim() || undefined;
|
|
142
|
+
out.push({
|
|
143
|
+
kind: mimeType ? kindFromMime(mimeType) : kindFromExt(p),
|
|
144
|
+
path: p,
|
|
145
|
+
...(mimeType ? { mimeType } : {}),
|
|
146
|
+
fileName: path.basename(p),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Remote-host variant of {@link resolveInboundAttachments}: the `imsg` bridge runs
|
|
153
|
+
* on a DIFFERENT machine, so each attachment's `original_path` is a REMOTE path.
|
|
154
|
+
* For each non-missing attachment whose remote path lives under an allowed remote
|
|
155
|
+
* root, SCP-copy it to a local temp file, then build the attachment pointing at
|
|
156
|
+
* the LOCAL copy (so the agent's `read` works). A copy failure drops just that
|
|
157
|
+
* attachment. Returns [] when nothing resolved.
|
|
158
|
+
*/
|
|
159
|
+
export async function resolveInboundAttachmentsRemote(raw, args) {
|
|
160
|
+
if (!Array.isArray(raw))
|
|
161
|
+
return [];
|
|
162
|
+
const out = [];
|
|
163
|
+
for (const att of raw) {
|
|
164
|
+
if (!att || att.missing === true)
|
|
165
|
+
continue;
|
|
166
|
+
const remotePath = (att.original_path ?? "").trim();
|
|
167
|
+
if (!remotePath)
|
|
168
|
+
continue;
|
|
169
|
+
if (args.remoteRoots.length > 0 && !isUnderAllowedRoot(remotePath, args.remoteRoots)) {
|
|
170
|
+
args.log?.(`dropping inbound attachment outside allowed remote roots: ${remotePath}`);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
let localPath;
|
|
174
|
+
try {
|
|
175
|
+
localPath = await scpCopyRemoteAttachment({
|
|
176
|
+
remoteHost: args.remoteHost,
|
|
177
|
+
remotePath,
|
|
178
|
+
...(args.scpRunner ? { scpRunner: args.scpRunner } : {}),
|
|
179
|
+
...(args.mkdtempImpl ? { mkdtempImpl: args.mkdtempImpl } : {}),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
args.log?.(`failed to fetch remote attachment ${remotePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const mimeType = (att.mime_type ?? "").trim() || undefined;
|
|
187
|
+
out.push({
|
|
188
|
+
kind: mimeType ? kindFromMime(mimeType) : kindFromExt(remotePath),
|
|
189
|
+
path: localPath,
|
|
190
|
+
...(mimeType ? { mimeType } : {}),
|
|
191
|
+
fileName: path.basename(remotePath),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
return out;
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=media.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/media.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage outbound-addressing adapter (the `ChannelPlugin.messaging` slot).
|
|
3
|
+
*
|
|
4
|
+
* Turns the loose `to` the agent hands `send_message` ("+1 555 123 4567",
|
|
5
|
+
* "imessage:user@example.com", "chat_id:42") into a concrete target the runtime
|
|
6
|
+
* `sendText` understands. iMessage has no contact DIRECTORY (no name→id
|
|
7
|
+
* resolution), so this implements only the required `parseExplicitTarget` +
|
|
8
|
+
* `normalizeTarget` (+ advisory `inferTargetChatType`); a bare human name falls
|
|
9
|
+
* through to the raw id, exactly as before.
|
|
10
|
+
*/
|
|
11
|
+
import type { ChannelMessagingAdapter } from "../sdk.js";
|
|
12
|
+
/** The iMessage messaging adapter. */
|
|
13
|
+
export declare const imessageMessagingAdapter: ChannelMessagingAdapter;
|
|
14
|
+
//# sourceMappingURL=messaging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/messaging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAwB,MAAM,WAAW,CAAC;AAO/E,sCAAsC;AACtC,eAAO,MAAM,wBAAwB,EAAE,uBAmBtC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage outbound-addressing adapter (the `ChannelPlugin.messaging` slot).
|
|
3
|
+
*
|
|
4
|
+
* Turns the loose `to` the agent hands `send_message` ("+1 555 123 4567",
|
|
5
|
+
* "imessage:user@example.com", "chat_id:42") into a concrete target the runtime
|
|
6
|
+
* `sendText` understands. iMessage has no contact DIRECTORY (no name→id
|
|
7
|
+
* resolution), so this implements only the required `parseExplicitTarget` +
|
|
8
|
+
* `normalizeTarget` (+ advisory `inferTargetChatType`); a bare human name falls
|
|
9
|
+
* through to the raw id, exactly as before.
|
|
10
|
+
*/
|
|
11
|
+
import { inferIMessageTargetChatType, looksLikeIMessageTargetId, normalizeIMessageHandle, } from "./targets.js";
|
|
12
|
+
/** The iMessage messaging adapter. */
|
|
13
|
+
export const imessageMessagingAdapter = {
|
|
14
|
+
parseExplicitTarget(text) {
|
|
15
|
+
const trimmed = (text ?? "").trim();
|
|
16
|
+
if (!trimmed)
|
|
17
|
+
return null;
|
|
18
|
+
// An explicit `imessage:<handle>` form names the channel.
|
|
19
|
+
const m = /^imessage:(.+)$/i.exec(trimmed);
|
|
20
|
+
if (m && m[1])
|
|
21
|
+
return { channelId: "imessage", target: m[1].trim() };
|
|
22
|
+
// A concrete chat/service/handle id (vs a bare name) is an explicit target.
|
|
23
|
+
if (looksLikeIMessageTargetId(trimmed))
|
|
24
|
+
return { target: trimmed };
|
|
25
|
+
return null;
|
|
26
|
+
},
|
|
27
|
+
normalizeTarget(raw) {
|
|
28
|
+
const trimmed = (raw ?? "").trim();
|
|
29
|
+
if (!trimmed)
|
|
30
|
+
return trimmed;
|
|
31
|
+
return normalizeIMessageHandle(trimmed);
|
|
32
|
+
},
|
|
33
|
+
inferTargetChatType(target) {
|
|
34
|
+
return inferIMessageTargetChatType(target);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=messaging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/messaging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACN,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,GACvB,MAAM,cAAc,CAAC;AAEtB,sCAAsC;AACtC,MAAM,CAAC,MAAM,wBAAwB,GAA4B;IAChE,mBAAmB,CAAC,IAAY;QAC/B,MAAM,OAAO,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,0DAA0D;QAC1D,MAAM,CAAC,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACrE,4EAA4E;QAC5E,IAAI,yBAAyB,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC;IACb,CAAC;IACD,eAAe,CAAC,GAAW;QAC1B,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC;QAC7B,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IACD,mBAAmB,CAAC,MAAc;QACjC,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;CACD,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage extension module.
|
|
3
|
+
*
|
|
4
|
+
* Registers the iMessage channel adapter through the seam. The loader gates it
|
|
5
|
+
* by the usual extension config (`extensions.disabled` / `entries`), and the
|
|
6
|
+
* adapter itself only starts when `channels.imessage.enabled` is true AND a
|
|
7
|
+
* runnable `imsg` binary resolves — so bundling this module is inert until the
|
|
8
|
+
* operator opts in.
|
|
9
|
+
*
|
|
10
|
+
* Like Discord, iMessage registers NO gateway HTTP route: the `imsg rpc`
|
|
11
|
+
* notification stream is the only inbound transport (a local subprocess, no
|
|
12
|
+
* public URL needed). iMessage mirror of `discord/module.ts` (the no-webhook
|
|
13
|
+
* shape).
|
|
14
|
+
*/
|
|
15
|
+
export declare const imessageModule: import("../sdk.js").BrigadeModule;
|
|
16
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,eAAO,MAAM,cAAc,mCAKzB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage extension module.
|
|
3
|
+
*
|
|
4
|
+
* Registers the iMessage channel adapter through the seam. The loader gates it
|
|
5
|
+
* by the usual extension config (`extensions.disabled` / `entries`), and the
|
|
6
|
+
* adapter itself only starts when `channels.imessage.enabled` is true AND a
|
|
7
|
+
* runnable `imsg` binary resolves — so bundling this module is inert until the
|
|
8
|
+
* operator opts in.
|
|
9
|
+
*
|
|
10
|
+
* Like Discord, iMessage registers NO gateway HTTP route: the `imsg rpc`
|
|
11
|
+
* notification stream is the only inbound transport (a local subprocess, no
|
|
12
|
+
* public URL needed). iMessage mirror of `discord/module.ts` (the no-webhook
|
|
13
|
+
* shape).
|
|
14
|
+
*/
|
|
15
|
+
import { defineModule } from "../sdk.js";
|
|
16
|
+
import { createIMessageAdapter } from "./adapter.js";
|
|
17
|
+
export const imessageModule = defineModule({
|
|
18
|
+
id: "imessage",
|
|
19
|
+
register(b) {
|
|
20
|
+
b.channel(createIMessageAdapter());
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC;IAC1C,EAAE,EAAE,UAAU;IACd,QAAQ,CAAC,CAAC;QACT,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACpC,CAAC;CACD,CAAC,CAAC"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage inbound monitor — parse notifications, normalize, and guard against
|
|
3
|
+
* self-echo / reflection / runaway loops.
|
|
4
|
+
*
|
|
5
|
+
* The `imsg rpc` process emits a `message` notification for every new row in the
|
|
6
|
+
* chat database (including the agent's OWN outbound sends, which come back as
|
|
7
|
+
* `is_from_me` rows, AND self-chat reflections). This module condenses the
|
|
8
|
+
* upstream `monitor/` subsystem into the load-bearing pieces:
|
|
9
|
+
*
|
|
10
|
+
* 1. `parseIMessageNotification` — validate + shape the notification params,
|
|
11
|
+
* stripping the protobuf length-prefix some text rows carry.
|
|
12
|
+
* 2. `normalizeIMessageMessage` — turn the payload into a normalized inbound.
|
|
13
|
+
* 3. `SentMessageCache` — remember every outbound send; drop the
|
|
14
|
+
* inbound echo when it matches (text TTL 4s / id TTL 60s).
|
|
15
|
+
* 4. `SelfChatCache` — drop a self-chat message reflected back as a
|
|
16
|
+
* second `is_from_me=false` row (TTL 10s, keyed on text + timestamp).
|
|
17
|
+
* 5. `detectReflectedContent` — drop inbound carrying assistant-internal
|
|
18
|
+
* markers that leaked out and bounced back.
|
|
19
|
+
* 6. `LoopRateLimiter` — after 5 loop-drops in 60s, mute a
|
|
20
|
+
* conversation entirely (the runaway-loop safety net).
|
|
21
|
+
* 7. `decideInbound` — the gating brain that ties them together.
|
|
22
|
+
*
|
|
23
|
+
* Constants are kept byte-faithful to the upstream so the dedupe windows behave
|
|
24
|
+
* identically.
|
|
25
|
+
*/
|
|
26
|
+
/** One raw inbound attachment as reported by the bridge. */
|
|
27
|
+
export interface IMessageRawAttachment {
|
|
28
|
+
original_path?: string | null;
|
|
29
|
+
mime_type?: string | null;
|
|
30
|
+
missing?: boolean | null;
|
|
31
|
+
}
|
|
32
|
+
/** The `message` field carried by an inbound notification (all fields optional). */
|
|
33
|
+
export interface IMessagePayload {
|
|
34
|
+
id?: number | null;
|
|
35
|
+
guid?: string | null;
|
|
36
|
+
chat_id?: number | null;
|
|
37
|
+
sender?: string | null;
|
|
38
|
+
destination_caller_id?: string | null;
|
|
39
|
+
is_from_me?: boolean | null;
|
|
40
|
+
text?: string | null;
|
|
41
|
+
reply_to_id?: number | string | null;
|
|
42
|
+
reply_to_text?: string | null;
|
|
43
|
+
reply_to_sender?: string | null;
|
|
44
|
+
created_at?: string | null;
|
|
45
|
+
attachments?: IMessageRawAttachment[] | null;
|
|
46
|
+
chat_identifier?: string | null;
|
|
47
|
+
chat_guid?: string | null;
|
|
48
|
+
chat_name?: string | null;
|
|
49
|
+
participants?: string[] | null;
|
|
50
|
+
is_group?: boolean | null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Strip a protobuf field-1 length-prefixed UTF-8 wrapper (tag `0x0a` + varint
|
|
54
|
+
* length + bytes) when the declared length consumes EXACTLY to the buffer end.
|
|
55
|
+
* Returns the inner string, or the original text unchanged.
|
|
56
|
+
*/
|
|
57
|
+
export declare function stripLengthPrefixedText(text: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Parse an inbound notification's `params` (`{ message: {...} }`) into a typed
|
|
60
|
+
* payload. Returns null when the shape is malformed (the caller drops it).
|
|
61
|
+
*/
|
|
62
|
+
export declare function parseIMessageNotification(raw: unknown): IMessagePayload | null;
|
|
63
|
+
/** A normalized inbound iMessage (pre-adapter shape). */
|
|
64
|
+
export interface NormalizedIMessage {
|
|
65
|
+
conversationId: string;
|
|
66
|
+
messageId?: string;
|
|
67
|
+
from: string;
|
|
68
|
+
fromName?: string;
|
|
69
|
+
text: string;
|
|
70
|
+
isGroup: boolean;
|
|
71
|
+
chatId?: number;
|
|
72
|
+
chatGuid?: string;
|
|
73
|
+
chatIdentifier?: string;
|
|
74
|
+
createdAtMs?: number;
|
|
75
|
+
replyTo?: {
|
|
76
|
+
messageId?: string;
|
|
77
|
+
body?: string;
|
|
78
|
+
from?: string;
|
|
79
|
+
};
|
|
80
|
+
attachments?: IMessageRawAttachment[];
|
|
81
|
+
/**
|
|
82
|
+
* Handles mentioned in this message. iMessage has no @-mention metadata, so
|
|
83
|
+
* this is populated only for a GROUP message when the bot's own `selfHandle`
|
|
84
|
+
* appears in the text — which is what lets the central pipeline's group
|
|
85
|
+
* requireMention gate fire. Unset when there's no match (or in DMs).
|
|
86
|
+
*/
|
|
87
|
+
mentions?: string[];
|
|
88
|
+
raw: IMessagePayload;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Detect whether the bot's own `selfHandle` is named in `text`. iMessage carries
|
|
92
|
+
* no @-mention metadata, so "mention" = the handle appearing in the message body.
|
|
93
|
+
* A phone handle matches on its digit-run inside the text's digits; an email
|
|
94
|
+
* matches case-insensitively. `selfHandle` is expected pre-normalised (digits for
|
|
95
|
+
* a phone, lower-case for an email — see `normalizeIMessageSelfHandle`). Returns
|
|
96
|
+
* the matched self handle in an array, or undefined when there's no match (so the
|
|
97
|
+
* field stays unset). Mirrors BlueBubbles' `detectBlueBubblesMentions`.
|
|
98
|
+
*/
|
|
99
|
+
export declare function detectIMessageMentions(text: string, selfHandle: string | undefined): string[] | undefined;
|
|
100
|
+
/** Build the stable conversation id for a payload (group → chat scope, DM → sender). */
|
|
101
|
+
export declare function conversationIdFor(payload: IMessagePayload): string;
|
|
102
|
+
/**
|
|
103
|
+
* Normalize a parsed payload into the inbound shape. When `selfHandle` is given
|
|
104
|
+
* and this is a GROUP message naming the bot, `mentions[]` is populated so the
|
|
105
|
+
* central group requireMention gate can fire.
|
|
106
|
+
*/
|
|
107
|
+
export declare function normalizeIMessageMessage(payload: IMessagePayload, selfHandle?: string): NormalizedIMessage;
|
|
108
|
+
/**
|
|
109
|
+
* Remembers every outbound send so the inbound poll can drop the echo. Keyed by
|
|
110
|
+
* a per-conversation `scope`; a text match (4s) or an id match (60s) suppresses
|
|
111
|
+
* the echo. Designed to degrade to a duplicate (noisy) rather than a dropped
|
|
112
|
+
* real message if an echo arrives after the TTL.
|
|
113
|
+
*/
|
|
114
|
+
export declare class SentMessageCache {
|
|
115
|
+
private readonly textCache;
|
|
116
|
+
private readonly idCache;
|
|
117
|
+
private readonly textBackedById;
|
|
118
|
+
/** Record an outbound send under `scope`. */
|
|
119
|
+
remember(scope: string, sent: {
|
|
120
|
+
text?: string;
|
|
121
|
+
messageId?: string;
|
|
122
|
+
}): void;
|
|
123
|
+
/** True when an inbound matches a remembered outbound (an echo). */
|
|
124
|
+
has(scope: string, inbound: {
|
|
125
|
+
text?: string;
|
|
126
|
+
messageId?: string;
|
|
127
|
+
}, skipIdShortCircuit?: boolean): boolean;
|
|
128
|
+
private cleanup;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Catches a self-chat message that arrives once as `is_from_me=true` and is then
|
|
132
|
+
* reflected as a second `is_from_me=false` row. Keyed on `scope:createdAt:hash`
|
|
133
|
+
* so it only fires when BOTH text and a timestamp anchor the same message.
|
|
134
|
+
*/
|
|
135
|
+
export declare class SelfChatCache {
|
|
136
|
+
private readonly cache;
|
|
137
|
+
private lastCleanup;
|
|
138
|
+
private buildKey;
|
|
139
|
+
remember(scope: string, text: string, createdAtMs?: number): void;
|
|
140
|
+
has(scope: string, text: string, createdAtMs?: number): boolean;
|
|
141
|
+
private maybeCleanup;
|
|
142
|
+
}
|
|
143
|
+
/** A `[start, end)` byte-index span of fenced or inline code inside a string. */
|
|
144
|
+
interface CodeRegion {
|
|
145
|
+
start: number;
|
|
146
|
+
end: number;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Find the code regions (fenced ``` / ~~~ blocks + inline backtick spans) in
|
|
150
|
+
* `text`. A reflection match that falls INSIDE one of these is a legit quoted
|
|
151
|
+
* sample, not a leaked assistant marker, so the guard ignores it. Ported byte-
|
|
152
|
+
* faithfully from the upstream `findCodeRegions`.
|
|
153
|
+
*/
|
|
154
|
+
export declare function findCodeRegions(text: string): CodeRegion[];
|
|
155
|
+
/** True when byte-index `pos` falls inside one of the code regions. */
|
|
156
|
+
export declare function isInsideCode(pos: number, regions: CodeRegion[]): boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Detect inbound text carrying assistant-internal markers (outbound metadata
|
|
159
|
+
* that leaked into the channel and bounced back). Returns the matched labels.
|
|
160
|
+
*
|
|
161
|
+
* A marker that appears INSIDE a fenced/inline code span is a legitimately
|
|
162
|
+
* quoted code sample (e.g. someone pasting `<final>` inside a ``` fence) and is
|
|
163
|
+
* NOT treated as a reflection — only matches OUTSIDE code count.
|
|
164
|
+
*/
|
|
165
|
+
export declare function detectReflectedContent(text: string): {
|
|
166
|
+
isReflection: boolean;
|
|
167
|
+
matchedLabels: string[];
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Per-conversation sliding-window counter. After {@link LOOP_MAX_HITS} loop
|
|
171
|
+
* drops within {@link LOOP_WINDOW_MS}, the conversation is rate-limited (muted)
|
|
172
|
+
* — the runaway-loop safety net.
|
|
173
|
+
*/
|
|
174
|
+
export declare class LoopRateLimiter {
|
|
175
|
+
private readonly hits;
|
|
176
|
+
private lastCleanup;
|
|
177
|
+
record(key: string): void;
|
|
178
|
+
isRateLimited(key: string): boolean;
|
|
179
|
+
private cleanup;
|
|
180
|
+
}
|
|
181
|
+
/** The dedupe/gating resources a monitor holds (one set per started account). */
|
|
182
|
+
export interface MonitorState {
|
|
183
|
+
sentMessageCache: SentMessageCache;
|
|
184
|
+
selfChatCache: SelfChatCache;
|
|
185
|
+
loopRateLimiter: LoopRateLimiter;
|
|
186
|
+
}
|
|
187
|
+
/** Build a fresh monitor state. */
|
|
188
|
+
export declare function createMonitorState(): MonitorState;
|
|
189
|
+
/** Build the echo/rate-limit scope for a payload. */
|
|
190
|
+
export declare function echoScope(accountId: string, payload: IMessagePayload): string;
|
|
191
|
+
/** The decision returned by {@link decideInbound}. */
|
|
192
|
+
export type InboundDecision = {
|
|
193
|
+
kind: "drop";
|
|
194
|
+
reason: string;
|
|
195
|
+
} | {
|
|
196
|
+
kind: "dispatch";
|
|
197
|
+
message: NormalizedIMessage;
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* The gating brain: parse → normalize → self-echo / self-chat / reflection
|
|
201
|
+
* dedupe → loop rate-limit. Pure given the (mutable) {@link MonitorState}.
|
|
202
|
+
* Loop-related drops feed the rate limiter; a rate-limited conversation drops a
|
|
203
|
+
* dispatch before it fires.
|
|
204
|
+
*/
|
|
205
|
+
export declare function decideInbound(state: MonitorState, accountId: string, payload: IMessagePayload, selfHandle?: string): InboundDecision;
|
|
206
|
+
export {};
|
|
207
|
+
//# sourceMappingURL=monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/monitor.ts"],"names":[],"mappings":"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"}
|