@spinabot/brigade 1.7.0 → 1.8.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/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/core/server.d.ts.map +1 -1
- package/dist/core/server.js +48 -2
- package/dist/core/server.js.map +1 -1
- 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 +1 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage outbound formatting helpers.
|
|
3
|
+
*
|
|
4
|
+
* iMessage has NO rich markup — a message is plain text. So unlike Telegram
|
|
5
|
+
* (HTML) or Discord (CommonMark), the only transform we need is to make markdown
|
|
6
|
+
* READABLE as plain text:
|
|
7
|
+
* - a markdown pipe-table is flattened to `cell | cell` lines (the LLM emits
|
|
8
|
+
* tables and an un-flattened one renders as raw `| --- |` noise);
|
|
9
|
+
* - everything else passes through untouched (bold `**x**`, links `[a](b)` —
|
|
10
|
+
* iMessage shows the literal characters, which is the honest fallback).
|
|
11
|
+
*
|
|
12
|
+
* Plus two send-path utilities ported from the upstream `send.ts`:
|
|
13
|
+
* - `sanitizeReplyToId` — scrub a reply-to id of control chars / brackets so it
|
|
14
|
+
* can't break the bridge's tag parsing, capped at 256 chars;
|
|
15
|
+
* - `resolveDeliveredText` — when an outbound has media but no text, deliver a
|
|
16
|
+
* `<media:kind>` placeholder so the echo cache + transcript have a body.
|
|
17
|
+
*/
|
|
18
|
+
/** Max length of a sanitized reply-to id. */
|
|
19
|
+
const MAX_REPLY_TO_ID_LENGTH = 256;
|
|
20
|
+
/**
|
|
21
|
+
* Flatten a markdown pipe-table block into plain `cell | cell` lines, dropping
|
|
22
|
+
* the `|---|` separator row. A non-table block is returned unchanged.
|
|
23
|
+
*/
|
|
24
|
+
function flattenTableBlock(lines) {
|
|
25
|
+
const out = [];
|
|
26
|
+
for (const line of lines) {
|
|
27
|
+
const trimmed = line.trim();
|
|
28
|
+
// Drop the header separator row (`| --- | --- |`).
|
|
29
|
+
if (/^\|?\s*:?-{2,}.*\|/.test(trimmed) && /^[\s|:-]+$/.test(trimmed))
|
|
30
|
+
continue;
|
|
31
|
+
const cells = trimmed
|
|
32
|
+
.replace(/^\|/, "")
|
|
33
|
+
.replace(/\|$/, "")
|
|
34
|
+
.split("|")
|
|
35
|
+
.map((c) => c.trim());
|
|
36
|
+
out.push(cells.join(" | "));
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
/** True when a line looks like a markdown table row (`| a | b |`). */
|
|
41
|
+
function isTableRow(line) {
|
|
42
|
+
const t = line.trim();
|
|
43
|
+
return t.startsWith("|") && t.includes("|", 1);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Convert agent-style markdown to iMessage-friendly plain text. The only
|
|
47
|
+
* load-bearing transform is flattening pipe tables; all other markdown passes
|
|
48
|
+
* through verbatim (iMessage renders the literal characters).
|
|
49
|
+
*/
|
|
50
|
+
export function markdownToIMessageText(markdown) {
|
|
51
|
+
const src = markdown ?? "";
|
|
52
|
+
if (!src.includes("|"))
|
|
53
|
+
return src; // fast path — no table possible
|
|
54
|
+
const lines = src.split("\n");
|
|
55
|
+
const out = [];
|
|
56
|
+
let i = 0;
|
|
57
|
+
while (i < lines.length) {
|
|
58
|
+
if (isTableRow(lines[i] ?? "")) {
|
|
59
|
+
const start = i;
|
|
60
|
+
while (i < lines.length && isTableRow(lines[i] ?? ""))
|
|
61
|
+
i++;
|
|
62
|
+
out.push(...flattenTableBlock(lines.slice(start, i)));
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
out.push(lines[i] ?? "");
|
|
66
|
+
i++;
|
|
67
|
+
}
|
|
68
|
+
return out.join("\n");
|
|
69
|
+
}
|
|
70
|
+
/** Strip control chars + `[` / `]` so a reply id can't break the bridge's tags. */
|
|
71
|
+
function stripUnsafeReplyTagChars(value) {
|
|
72
|
+
let out = "";
|
|
73
|
+
for (const ch of value) {
|
|
74
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
75
|
+
if (code <= 31 || code === 127)
|
|
76
|
+
continue;
|
|
77
|
+
if (ch === "[" || ch === "]")
|
|
78
|
+
continue;
|
|
79
|
+
out += ch;
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sanitize an outbound reply-to id: trim, strip unsafe chars, cap at 256 chars.
|
|
85
|
+
* Returns undefined when nothing usable remains.
|
|
86
|
+
*/
|
|
87
|
+
export function sanitizeReplyToId(raw) {
|
|
88
|
+
const trimmed = (raw ?? "").trim();
|
|
89
|
+
if (!trimmed)
|
|
90
|
+
return undefined;
|
|
91
|
+
let v = stripUnsafeReplyTagChars(trimmed).trim();
|
|
92
|
+
if (!v)
|
|
93
|
+
return undefined;
|
|
94
|
+
if (v.length > MAX_REPLY_TO_ID_LENGTH)
|
|
95
|
+
v = v.slice(0, MAX_REPLY_TO_ID_LENGTH);
|
|
96
|
+
return v;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Outbound delivery sanitizer (the twin of the inbound reflection guard).
|
|
100
|
+
*
|
|
101
|
+
* The central pipeline already strips `<think>`/`<final>` via
|
|
102
|
+
* `sanitizeReplyForChannel`, but the channel send path is reachable by OTHER
|
|
103
|
+
* routes (agent tools, catch-up replays, plugins) and a model can emit Brigade's
|
|
104
|
+
* own internal scaffolding mid-text. This is the last gate before the wire: it
|
|
105
|
+
* removes anything that is unambiguously internal so it can never reach a
|
|
106
|
+
* recipient's iMessage thread. Shared by BOTH channels (iMessage native +
|
|
107
|
+
* BlueBubbles) — it runs on every outbound text bubble.
|
|
108
|
+
*
|
|
109
|
+
* What it strips:
|
|
110
|
+
* - inline directive tags (`[[audio_as_voice]]`, `[[reply_to:…]]`,
|
|
111
|
+
* `[[reply_to_current]]`) — Brigade consumes these as send-options; they
|
|
112
|
+
* must never render as literal text;
|
|
113
|
+
* - `<think>`/`<thinking>`/`<thought>` reasoning blocks + `<final>` wrappers
|
|
114
|
+
* (residue if an upstream sanitizer was skipped);
|
|
115
|
+
* - role/turn scaffolding markers (`assistant to=…`, a trailing
|
|
116
|
+
* `user:` / `system:` / `assistant:` line) and internal `#+#+` separators.
|
|
117
|
+
*
|
|
118
|
+
* Idempotent + dependency-free. Collapses the blank lines a strip leaves behind.
|
|
119
|
+
*/
|
|
120
|
+
/** Inline directive tags Brigade consumes as send-options (never user-visible). */
|
|
121
|
+
const INLINE_DIRECTIVE_TAG_RE = /\s*(?:\[\[\s*audio_as_voice\s*\]\]|\[\[\s*(?:reply_to_current|reply_to\s*:\s*[^\]\n]+)\s*\]\])\s*/gi;
|
|
122
|
+
/** Model-internal separator runs (`+#+#+#`). */
|
|
123
|
+
const INTERNAL_SEPARATOR_RE = /(?:[#+]){4,}#?/g;
|
|
124
|
+
/** A leaked `assistant to=<role>` scaffolding marker. */
|
|
125
|
+
const ASSISTANT_ROLE_MARKER_RE = /\bassistant\s+to\s*=\s*\w+/gi;
|
|
126
|
+
/** A trailing role-turn marker on its own line (`assistant:` / `user:` / `system:`). */
|
|
127
|
+
const ROLE_TURN_MARKER_RE = /^[ \t]*(?:user|system|assistant)\s*:\s*$/gim;
|
|
128
|
+
/** Iteratively drop fully-closed `<think>`/`<thinking>`/`<thought>` blocks. */
|
|
129
|
+
function stripReasoningBlocks(text) {
|
|
130
|
+
let out = text;
|
|
131
|
+
for (let i = 0; i < 32; i++) {
|
|
132
|
+
const next = out.replace(/<(think|thinking|thought)>(?:(?!<\1>)[\s\S])*?<\/\1>\s*/i, "");
|
|
133
|
+
if (next === out)
|
|
134
|
+
break;
|
|
135
|
+
out = next;
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Strip Brigade-internal scaffolding from outbound text before it hits the wire.
|
|
141
|
+
* Returns the cleaned text; if stripping leaves nothing, returns the trimmed
|
|
142
|
+
* original (better to send something than confuse the recipient with silence).
|
|
143
|
+
*/
|
|
144
|
+
export function sanitizeOutboundIMessageText(text) {
|
|
145
|
+
if (!text)
|
|
146
|
+
return text;
|
|
147
|
+
let cleaned = stripReasoningBlocks(text);
|
|
148
|
+
cleaned = cleaned.replace(/<\/?final>\s*/gi, "");
|
|
149
|
+
cleaned = cleaned.replace(INLINE_DIRECTIVE_TAG_RE, " ");
|
|
150
|
+
cleaned = cleaned.replace(INTERNAL_SEPARATOR_RE, "");
|
|
151
|
+
cleaned = cleaned.replace(ASSISTANT_ROLE_MARKER_RE, "");
|
|
152
|
+
cleaned = cleaned.replace(ROLE_TURN_MARKER_RE, "");
|
|
153
|
+
// Collapse runs of spaces a strip can leave mid-line, then blank lines.
|
|
154
|
+
cleaned = cleaned.replace(/[ \t]{2,}/g, " ").replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
155
|
+
const trimmed = cleaned.trim();
|
|
156
|
+
return trimmed.length > 0 ? trimmed : text.trim();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* When an outbound carries media but no text, deliver a `<media:kind>`
|
|
160
|
+
* placeholder so the echo cache + transcript have a body to key on. Returns the
|
|
161
|
+
* text unchanged when it's non-empty.
|
|
162
|
+
*/
|
|
163
|
+
export function resolveDeliveredText(text, mediaKind) {
|
|
164
|
+
if ((text ?? "").trim())
|
|
165
|
+
return text;
|
|
166
|
+
if (!mediaKind)
|
|
167
|
+
return text;
|
|
168
|
+
return `<media:${mediaKind}>`;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,6CAA6C;AAC7C,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC;;;GAGG;AACH,SAAS,iBAAiB,CAAC,KAAe;IACzC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,mDAAmD;QACnD,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,SAAS;QAC/E,MAAM,KAAK,GAAG,OAAO;aACnB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;aAClB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;aAClB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACvB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,sEAAsE;AACtE,SAAS,UAAU,CAAC,IAAY;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACtD,MAAM,GAAG,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,CAAC,gCAAgC;IACpE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACzB,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAAE,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,SAAS;QACV,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,EAAE,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,mFAAmF;AACnF,SAAS,wBAAwB,CAAC,KAAa;IAC9C,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI,KAAK,GAAG;YAAE,SAAS;QACzC,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,SAAS;QACvC,GAAG,IAAI,EAAE,CAAC;IACX,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC7C,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,CAAC,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,IAAI,CAAC,CAAC,MAAM,GAAG,sBAAsB;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;IAC9E,OAAO,CAAC,CAAC;AACV,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,mFAAmF;AACnF,MAAM,uBAAuB,GAC5B,qGAAqG,CAAC;AACvG,gDAAgD;AAChD,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AAChD,yDAAyD;AACzD,MAAM,wBAAwB,GAAG,8BAA8B,CAAC;AAChE,wFAAwF;AACxF,MAAM,mBAAmB,GAAG,6CAA6C,CAAC;AAE1E,+EAA+E;AAC/E,SAAS,oBAAoB,CAAC,IAAY;IACzC,IAAI,GAAG,GAAG,IAAI,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,0DAA0D,EAAE,EAAE,CAAC,CAAC;QACzF,IAAI,IAAI,KAAK,GAAG;YAAE,MAAM;QACxB,GAAG,GAAG,IAAI,CAAC;IACZ,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAY;IACxD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,IAAI,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACnD,wEAAwE;IACxE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACnG,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACnD,CAAC;AAMD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,SAA6B;IAC/E,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,UAAU,SAAS,GAAG,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage rolling group-history context.
|
|
3
|
+
*
|
|
4
|
+
* iMessage delivers ONE `imsg rpc` notification per new message with no thread
|
|
5
|
+
* context — so when an untagged group message arrives, the agent has no idea
|
|
6
|
+
* what the room was just talking about. Unlike BlueBubbles (which exposes an
|
|
7
|
+
* HTTP message-listing endpoint), the `imsg rpc` transport exposes NO history /
|
|
8
|
+
* `chats.messages` method (its only calls are `chats.list`, `send`,
|
|
9
|
+
* `watch.subscribe`). So — exactly as the upstream iMessage monitor does — we
|
|
10
|
+
* keep a small ROLLING in-memory buffer of the last N text-bearing messages
|
|
11
|
+
* we've already seen per conversation, and prepend them as a fenced
|
|
12
|
+
* `[recent conversation context]` block to an untagged message's body.
|
|
13
|
+
*
|
|
14
|
+
* The buffer is bounded (`limit` entries per conversation) and the message the
|
|
15
|
+
* context is built FOR is appended only AFTER its block is rendered, so a
|
|
16
|
+
* message never quotes itself.
|
|
17
|
+
*/
|
|
18
|
+
/** One compact rolling-history line. */
|
|
19
|
+
export interface IMessageHistoryEntry {
|
|
20
|
+
/** Display label of the speaker (handle / name, or "me" for the bot's own past sends). */
|
|
21
|
+
sender: string;
|
|
22
|
+
/** Message text (truncated). */
|
|
23
|
+
body: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Per-account rolling buffer of recent messages, keyed by conversation id. Pure
|
|
27
|
+
* in-memory (no I/O); one instance lives in each connection's closure.
|
|
28
|
+
*/
|
|
29
|
+
export declare class IMessageHistoryBuffer {
|
|
30
|
+
private readonly byConversation;
|
|
31
|
+
/**
|
|
32
|
+
* Return the last `limit` entries for `conversationId` (oldest-first), rendered
|
|
33
|
+
* to the caller. Returns [] when nothing is buffered or `limit <= 0`.
|
|
34
|
+
*/
|
|
35
|
+
recent(conversationId: string, limit: number): IMessageHistoryEntry[];
|
|
36
|
+
/**
|
|
37
|
+
* Append a seen message to the conversation's buffer (empty bodies are
|
|
38
|
+
* ignored). The buffer is trimmed to `MAX_HISTORY_ENTRIES`.
|
|
39
|
+
*/
|
|
40
|
+
record(conversationId: string, entry: IMessageHistoryEntry): void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Render rolling-history entries as a clearly-fenced context block to PREPEND to
|
|
44
|
+
* an inbound body. Returns "" when there are no entries. The block is delimited
|
|
45
|
+
* so the agent can tell prior context from the current message. Mirrors
|
|
46
|
+
* BlueBubbles' `renderBlueBubblesHistoryBlock`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function renderIMessageHistoryBlock(entries: IMessageHistoryEntry[]): string;
|
|
49
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,wCAAwC;AACxC,MAAM,WAAW,oBAAoB;IACpC,0FAA0F;IAC1F,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;CACb;AAcD;;;GAGG;AACH,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6C;IAE5E;;;OAGG;IACH,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAOrE;;;OAGG;IACH,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,GAAG,IAAI;CAQjE;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAIlF"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage rolling group-history context.
|
|
3
|
+
*
|
|
4
|
+
* iMessage delivers ONE `imsg rpc` notification per new message with no thread
|
|
5
|
+
* context — so when an untagged group message arrives, the agent has no idea
|
|
6
|
+
* what the room was just talking about. Unlike BlueBubbles (which exposes an
|
|
7
|
+
* HTTP message-listing endpoint), the `imsg rpc` transport exposes NO history /
|
|
8
|
+
* `chats.messages` method (its only calls are `chats.list`, `send`,
|
|
9
|
+
* `watch.subscribe`). So — exactly as the upstream iMessage monitor does — we
|
|
10
|
+
* keep a small ROLLING in-memory buffer of the last N text-bearing messages
|
|
11
|
+
* we've already seen per conversation, and prepend them as a fenced
|
|
12
|
+
* `[recent conversation context]` block to an untagged message's body.
|
|
13
|
+
*
|
|
14
|
+
* The buffer is bounded (`limit` entries per conversation) and the message the
|
|
15
|
+
* context is built FOR is appended only AFTER its block is rendered, so a
|
|
16
|
+
* message never quotes itself.
|
|
17
|
+
*/
|
|
18
|
+
/** Cap on a single history line's length (keeps the context block bounded). */
|
|
19
|
+
const MAX_HISTORY_BODY_CHARS = 2_000;
|
|
20
|
+
/** Hard ceiling on entries retained per conversation regardless of `limit`. */
|
|
21
|
+
const MAX_HISTORY_ENTRIES = 100;
|
|
22
|
+
/** Truncate a history line body, marking the cut. */
|
|
23
|
+
function truncateBody(text) {
|
|
24
|
+
const t = text.trim();
|
|
25
|
+
if (t.length <= MAX_HISTORY_BODY_CHARS)
|
|
26
|
+
return t;
|
|
27
|
+
return `${t.slice(0, MAX_HISTORY_BODY_CHARS).trimEnd()}...`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Per-account rolling buffer of recent messages, keyed by conversation id. Pure
|
|
31
|
+
* in-memory (no I/O); one instance lives in each connection's closure.
|
|
32
|
+
*/
|
|
33
|
+
export class IMessageHistoryBuffer {
|
|
34
|
+
byConversation = new Map();
|
|
35
|
+
/**
|
|
36
|
+
* Return the last `limit` entries for `conversationId` (oldest-first), rendered
|
|
37
|
+
* to the caller. Returns [] when nothing is buffered or `limit <= 0`.
|
|
38
|
+
*/
|
|
39
|
+
recent(conversationId, limit) {
|
|
40
|
+
if (limit <= 0)
|
|
41
|
+
return [];
|
|
42
|
+
const arr = this.byConversation.get(conversationId);
|
|
43
|
+
if (!arr || arr.length === 0)
|
|
44
|
+
return [];
|
|
45
|
+
return arr.slice(-limit);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Append a seen message to the conversation's buffer (empty bodies are
|
|
49
|
+
* ignored). The buffer is trimmed to `MAX_HISTORY_ENTRIES`.
|
|
50
|
+
*/
|
|
51
|
+
record(conversationId, entry) {
|
|
52
|
+
const body = truncateBody(entry.body ?? "");
|
|
53
|
+
if (!body)
|
|
54
|
+
return;
|
|
55
|
+
const arr = this.byConversation.get(conversationId) ?? [];
|
|
56
|
+
arr.push({ sender: entry.sender || "Unknown", body });
|
|
57
|
+
while (arr.length > MAX_HISTORY_ENTRIES)
|
|
58
|
+
arr.shift();
|
|
59
|
+
this.byConversation.set(conversationId, arr);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Render rolling-history entries as a clearly-fenced context block to PREPEND to
|
|
64
|
+
* an inbound body. Returns "" when there are no entries. The block is delimited
|
|
65
|
+
* so the agent can tell prior context from the current message. Mirrors
|
|
66
|
+
* BlueBubbles' `renderBlueBubblesHistoryBlock`.
|
|
67
|
+
*/
|
|
68
|
+
export function renderIMessageHistoryBlock(entries) {
|
|
69
|
+
if (!entries || entries.length === 0)
|
|
70
|
+
return "";
|
|
71
|
+
const lines = entries.map((e) => `${e.sender}: ${e.body}`);
|
|
72
|
+
return ["[recent conversation context]", ...lines, "[end context]"].join("\n");
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAUH,+EAA+E;AAC/E,MAAM,sBAAsB,GAAG,KAAK,CAAC;AACrC,+EAA+E;AAC/E,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,qDAAqD;AACrD,SAAS,YAAY,CAAC,IAAY;IACjC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,IAAI,CAAC,CAAC,MAAM,IAAI,sBAAsB;QAAE,OAAO,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IAChB,cAAc,GAAG,IAAI,GAAG,EAAkC,CAAC;IAE5E;;;OAGG;IACH,MAAM,CAAC,cAAsB,EAAE,KAAa;QAC3C,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACpD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACxC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,cAAsB,EAAE,KAA2B;QACzD,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC1D,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,OAAO,GAAG,CAAC,MAAM,GAAG,mBAAmB;YAAE,GAAG,CAAC,KAAK,EAAE,CAAC;QACrD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IAC9C,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAA+B;IACzE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,+BAA+B,EAAE,GAAG,KAAK,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage channel — public barrel.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the channel's public surface (adapter / plugin / config helpers /
|
|
5
|
+
* transport client / send / probe / targets) so the gateway boot + the central
|
|
6
|
+
* registries can import from one place, mirroring `telegram/index.ts` and
|
|
7
|
+
* `discord/index.ts`.
|
|
8
|
+
*/
|
|
9
|
+
export { createIMessageAdapter, IMESSAGE_CAPABILITIES, type CreateIMessageAdapterOptions, } from "./adapter.js";
|
|
10
|
+
export { coerceIMessageChunkMode, imessageChannelEnabled, imessageThreadIdleTtlMs, listIMessageAccountIds, normalizeIMessageSelfHandle, resolveIMessageAccount, resolveIMessageAttachmentRoots, resolveIMessageChunkMode, resolveIMessageCliPath, resolveIMessageDbPath, resolveIMessageDefaultTo, resolveIMessageDmHistoryLimit, resolveIMessageHistoryLimit, resolveIMessageIncludeAttachments, resolveIMessageProbeTimeoutMs, resolveIMessageRemoteAttachmentRoots, resolveIMessageRemoteHost, resolveIMessageSelfHandle, resolveIMessageTextChunkLimit, DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, DEFAULT_IMESSAGE_HISTORY_LIMIT, DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS, DEFAULT_IMESSAGE_TEXT_CHUNK_LIMIT, IMESSAGE_CHANNEL_ID, IMESSAGE_DEFAULT_ACCOUNT_ID, IMESSAGE_CLI_PATH_ENV_VAR, type IMessageChunkMode, type IMessageService, type ResolvedIMessageAccount, } from "./account-config.js";
|
|
11
|
+
export { createIMessageRpcClient, IMessageRpcClient, isTestEnv, type IMessageRpcLike, type IMessageRpcNotification, type IMessageRpcClientOptions, } from "./client.js";
|
|
12
|
+
export { connectIMessage, type ConnectIMessageArgs, type IMessageConnection, type IMessageInboundMessage, } from "./connection.js";
|
|
13
|
+
export { markdownToIMessageText, sanitizeReplyToId, resolveDeliveredText } from "./format.js";
|
|
14
|
+
export { resolveOutboundAttachment, resolveInboundAttachments, resolveInboundAttachmentsRemote, kindFromMime, } from "./media.js";
|
|
15
|
+
export { imessageMessagingAdapter } from "./messaging.js";
|
|
16
|
+
export { createMonitorState, decideInbound, detectIMessageMentions, detectReflectedContent, findCodeRegions, isInsideCode, normalizeIMessageMessage, parseIMessageNotification, stripLengthPrefixedText, LoopRateLimiter, SelfChatCache, SentMessageCache, type IMessagePayload, type NormalizedIMessage, } from "./monitor.js";
|
|
17
|
+
export { IMessageHistoryBuffer, renderIMessageHistoryBlock, type IMessageHistoryEntry } from "./history.js";
|
|
18
|
+
export { detectRemoteHostFromCliPath, normalizeScpRemoteHost, scpCopyRemoteAttachment, } from "./remote-attachments.js";
|
|
19
|
+
export { sanitizeIMessageWatchErrorPayload, type SanitizedIMessageWatchErrorPayload, } from "./watch-error.js";
|
|
20
|
+
export { createIMessagePlugin, type IMessagePluginDeps, type IMessagePluginHandle } from "./plugin.js";
|
|
21
|
+
export { probeIMessage, probeRpcSupport, type IMessageProbeResult } from "./probe.js";
|
|
22
|
+
export { sendMessageIMessage, type IMessageSendOpts, type IMessageSendResult } from "./send.js";
|
|
23
|
+
export { formatIMessageChatTarget, inferIMessageTargetChatType, isAllowedIMessageSender, normalizeE164, normalizeIMessageHandle, parseIMessageAllowTarget, parseIMessageTarget, type IMessageTarget, type IMessageAllowTarget, } from "./targets.js";
|
|
24
|
+
export { imessageModule } from "./module.js";
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACN,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,4BAA4B,GACjC,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,2BAA2B,EAC3B,sBAAsB,EACtB,8BAA8B,EAC9B,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,iCAAiC,EACjC,6BAA6B,EAC7B,oCAAoC,EACpC,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,iCAAiC,EACjC,8BAA8B,EAC9B,iCAAiC,EACjC,iCAAiC,EACjC,mBAAmB,EACnB,2BAA2B,EAC3B,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,uBAAuB,GAC5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,uBAAuB,EACvB,iBAAiB,EACjB,SAAS,EACT,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,eAAe,EACf,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9F,OAAO,EACN,yBAAyB,EACzB,yBAAyB,EACzB,+BAA+B,EAC/B,YAAY,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACN,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC5G,OAAO,EACN,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,iCAAiC,EACjC,KAAK,kCAAkC,GACvC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAChG,OAAO,EACN,wBAAwB,EACxB,2BAA2B,EAC3B,uBAAuB,EACvB,aAAa,EACb,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iMessage channel — public barrel.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the channel's public surface (adapter / plugin / config helpers /
|
|
5
|
+
* transport client / send / probe / targets) so the gateway boot + the central
|
|
6
|
+
* registries can import from one place, mirroring `telegram/index.ts` and
|
|
7
|
+
* `discord/index.ts`.
|
|
8
|
+
*/
|
|
9
|
+
export { createIMessageAdapter, IMESSAGE_CAPABILITIES, } from "./adapter.js";
|
|
10
|
+
export { coerceIMessageChunkMode, imessageChannelEnabled, imessageThreadIdleTtlMs, listIMessageAccountIds, normalizeIMessageSelfHandle, resolveIMessageAccount, resolveIMessageAttachmentRoots, resolveIMessageChunkMode, resolveIMessageCliPath, resolveIMessageDbPath, resolveIMessageDefaultTo, resolveIMessageDmHistoryLimit, resolveIMessageHistoryLimit, resolveIMessageIncludeAttachments, resolveIMessageProbeTimeoutMs, resolveIMessageRemoteAttachmentRoots, resolveIMessageRemoteHost, resolveIMessageSelfHandle, resolveIMessageTextChunkLimit, DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, DEFAULT_IMESSAGE_HISTORY_LIMIT, DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS, DEFAULT_IMESSAGE_TEXT_CHUNK_LIMIT, IMESSAGE_CHANNEL_ID, IMESSAGE_DEFAULT_ACCOUNT_ID, IMESSAGE_CLI_PATH_ENV_VAR, } from "./account-config.js";
|
|
11
|
+
export { createIMessageRpcClient, IMessageRpcClient, isTestEnv, } from "./client.js";
|
|
12
|
+
export { connectIMessage, } from "./connection.js";
|
|
13
|
+
export { markdownToIMessageText, sanitizeReplyToId, resolveDeliveredText } from "./format.js";
|
|
14
|
+
export { resolveOutboundAttachment, resolveInboundAttachments, resolveInboundAttachmentsRemote, kindFromMime, } from "./media.js";
|
|
15
|
+
export { imessageMessagingAdapter } from "./messaging.js";
|
|
16
|
+
export { createMonitorState, decideInbound, detectIMessageMentions, detectReflectedContent, findCodeRegions, isInsideCode, normalizeIMessageMessage, parseIMessageNotification, stripLengthPrefixedText, LoopRateLimiter, SelfChatCache, SentMessageCache, } from "./monitor.js";
|
|
17
|
+
export { IMessageHistoryBuffer, renderIMessageHistoryBlock } from "./history.js";
|
|
18
|
+
export { detectRemoteHostFromCliPath, normalizeScpRemoteHost, scpCopyRemoteAttachment, } from "./remote-attachments.js";
|
|
19
|
+
export { sanitizeIMessageWatchErrorPayload, } from "./watch-error.js";
|
|
20
|
+
export { createIMessagePlugin } from "./plugin.js";
|
|
21
|
+
export { probeIMessage, probeRpcSupport } from "./probe.js";
|
|
22
|
+
export { sendMessageIMessage } from "./send.js";
|
|
23
|
+
export { formatIMessageChatTarget, inferIMessageTargetChatType, isAllowedIMessageSender, normalizeE164, normalizeIMessageHandle, parseIMessageAllowTarget, parseIMessageTarget, } from "./targets.js";
|
|
24
|
+
export { imessageModule } from "./module.js";
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACN,qBAAqB,EACrB,qBAAqB,GAErB,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,2BAA2B,EAC3B,sBAAsB,EACtB,8BAA8B,EAC9B,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,iCAAiC,EACjC,6BAA6B,EAC7B,oCAAoC,EACpC,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,iCAAiC,EACjC,8BAA8B,EAC9B,iCAAiC,EACjC,iCAAiC,EACjC,mBAAmB,EACnB,2BAA2B,EAC3B,yBAAyB,GAIzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,uBAAuB,EACvB,iBAAiB,EACjB,SAAS,GAIT,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,eAAe,GAIf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9F,OAAO,EACN,yBAAyB,EACzB,yBAAyB,EACzB,+BAA+B,EAC/B,YAAY,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EACN,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,eAAe,EACf,aAAa,EACb,gBAAgB,GAGhB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAA6B,MAAM,cAAc,CAAC;AAC5G,OAAO,EACN,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,GACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,iCAAiC,GAEjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAsD,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,aAAa,EAAE,eAAe,EAA4B,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAkD,MAAM,WAAW,CAAC;AAChG,OAAO,EACN,wBAAwB,EACxB,2BAA2B,EAC3B,uBAAuB,EACvB,aAAa,EACb,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,GAGnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
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 { type InboundMediaAttachment, type OutboundMedia } from "../sdk.js";
|
|
19
|
+
import { type ScpCopyArgs } from "./remote-attachments.js";
|
|
20
|
+
/** Brigade media kinds an attachment can be. */
|
|
21
|
+
type MediaKind = OutboundMedia["kind"];
|
|
22
|
+
/** Map a MIME type to a Brigade media kind (defaults to `document`). */
|
|
23
|
+
export declare function kindFromMime(mime?: string): MediaKind;
|
|
24
|
+
/** Map a file extension to a Brigade media kind (defaults to `document`). */
|
|
25
|
+
export declare function kindFromExt(filePath: string): MediaKind;
|
|
26
|
+
/** Result of resolving an outbound attachment for the send path. */
|
|
27
|
+
export interface ResolvedOutboundAttachment {
|
|
28
|
+
/** Absolute local path the RPC's `file` param points at. */
|
|
29
|
+
path: string;
|
|
30
|
+
/** Inferred media kind (for the `<media:kind>` placeholder when text is empty). */
|
|
31
|
+
kind: MediaKind;
|
|
32
|
+
/** Inferred MIME type, when known. */
|
|
33
|
+
mimeType?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve an outbound media path for the send RPC: run the exfil guard, enforce
|
|
37
|
+
* the size cap, and infer the kind. Throws an operator-facing error when the
|
|
38
|
+
* path is refused or too large.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveOutboundAttachment(rawPath: string, maxBytes: number): ResolvedOutboundAttachment;
|
|
41
|
+
/**
|
|
42
|
+
* Build an OutboundMedia descriptor's `kind` for a path (used when the caller
|
|
43
|
+
* already validated the path). Mirrors `kindFromExt` but kept as a named export
|
|
44
|
+
* so callers read clearly.
|
|
45
|
+
*/
|
|
46
|
+
export declare function inferOutboundMediaKind(media: OutboundMedia): MediaKind;
|
|
47
|
+
/**
|
|
48
|
+
* True when a resolved on-disk path lives under one of the allowed roots.
|
|
49
|
+
*
|
|
50
|
+
* Roots are POSIX-style macOS paths (the bridge reports paths from a Mac), so
|
|
51
|
+
* matching is done on forward-slash-normalised strings — NOT `path.resolve`,
|
|
52
|
+
* which on Windows would drive-root a leading-slash path and flip the separators
|
|
53
|
+
* (breaking the glob-tail check). A wildcard segment in a root (e.g. the user
|
|
54
|
+
* segment in /Users/<wildcard>/Library/Messages/Attachments) matches any single
|
|
55
|
+
* path segment.
|
|
56
|
+
*/
|
|
57
|
+
export declare function isUnderAllowedRoot(filePath: string, roots: readonly string[]): boolean;
|
|
58
|
+
/** One raw inbound attachment as reported by the `imsg` bridge. */
|
|
59
|
+
export interface RawInboundAttachment {
|
|
60
|
+
original_path?: string | null;
|
|
61
|
+
mime_type?: string | null;
|
|
62
|
+
missing?: boolean | null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Map the bridge's reported inbound attachments to Brigade `InboundMediaAttachment`s,
|
|
66
|
+
* dropping any that are missing or whose on-disk path falls outside the allowed
|
|
67
|
+
* roots. Returns [] when nothing resolved.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveInboundAttachments(raw: RawInboundAttachment[] | null | undefined, allowedRoots: readonly string[]): InboundMediaAttachment[];
|
|
70
|
+
/** Options for {@link resolveInboundAttachmentsRemote}. */
|
|
71
|
+
export interface RemoteInboundAttachmentArgs {
|
|
72
|
+
/** Validated remote host (`user@host` / `host`). */
|
|
73
|
+
remoteHost: string;
|
|
74
|
+
/** Allowed REMOTE attachment roots the remote `original_path` must live under. */
|
|
75
|
+
remoteRoots: readonly string[];
|
|
76
|
+
/** TEST SEAM: the scp runner + temp-dir factory used by the copy. */
|
|
77
|
+
scpRunner?: ScpCopyArgs["scpRunner"];
|
|
78
|
+
mkdtempImpl?: ScpCopyArgs["mkdtempImpl"];
|
|
79
|
+
/** Best-effort log for a dropped / failed remote attachment. */
|
|
80
|
+
log?: (msg: string) => void;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Remote-host variant of {@link resolveInboundAttachments}: the `imsg` bridge runs
|
|
84
|
+
* on a DIFFERENT machine, so each attachment's `original_path` is a REMOTE path.
|
|
85
|
+
* For each non-missing attachment whose remote path lives under an allowed remote
|
|
86
|
+
* root, SCP-copy it to a local temp file, then build the attachment pointing at
|
|
87
|
+
* the LOCAL copy (so the agent's `read` works). A copy failure drops just that
|
|
88
|
+
* attachment. Returns [] when nothing resolved.
|
|
89
|
+
*/
|
|
90
|
+
export declare function resolveInboundAttachmentsRemote(raw: RawInboundAttachment[] | null | undefined, args: RemoteInboundAttachmentArgs): Promise<InboundMediaAttachment[]>;
|
|
91
|
+
export {};
|
|
92
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/imessage/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,OAAO,EAA6B,KAAK,sBAAsB,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AACvG,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEpF,gDAAgD;AAChD,KAAK,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAEvC,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAMrD;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAMvD;AAED,oEAAoE;AACpE,MAAM,WAAW,0BAA0B;IAC1C,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,IAAI,EAAE,SAAS,CAAC;IAChB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,0BAA0B,CAmBvG;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CAGtE;AAOD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAoBtF;AAED,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACpC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,oBAAoB,EAAE,GAAG,IAAI,GAAG,SAAS,EAC9C,YAAY,EAAE,SAAS,MAAM,EAAE,GAC7B,sBAAsB,EAAE,CAiB1B;AAED,2DAA2D;AAC3D,MAAM,WAAW,2BAA2B;IAC3C,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,qEAAqE;IACrE,SAAS,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IACzC,gEAAgE;IAChE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACpD,GAAG,EAAE,oBAAoB,EAAE,GAAG,IAAI,GAAG,SAAS,EAC9C,IAAI,EAAE,2BAA2B,GAC/B,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAgCnC"}
|