flow-agent-bridge 0.37.3 → 0.37.7
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/api.d.ts +39 -2
- package/dist/api.js +49 -6
- package/dist/api.js.map +1 -1
- package/dist/bridge.d.ts +68 -0
- package/dist/bridge.js +364 -15
- package/dist/bridge.js.map +1 -1
- package/dist/calendar-tools.d.ts +194 -0
- package/dist/calendar-tools.js +258 -0
- package/dist/calendar-tools.js.map +1 -0
- package/dist/catch-up.d.ts +50 -0
- package/dist/catch-up.js +137 -0
- package/dist/catch-up.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/gateway.d.ts +17 -1
- package/dist/gateway.js +41 -2
- package/dist/gateway.js.map +1 -1
- package/dist/mcp-server.js +28 -6
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
export const CALENDAR_TOOLS = [
|
|
2
|
+
{
|
|
3
|
+
name: 'list_my_events',
|
|
4
|
+
description: 'List the events on your own calendars between two times (at most three months apart): id, when, title, organizer and your answer. Invitations you have not answered show "needs-action".',
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
from: { type: 'string', description: 'Start of the window, an ISO time, e.g. 2026-12-01T00:00:00Z.' },
|
|
9
|
+
to: { type: 'string', description: 'End of the window, an ISO time.' },
|
|
10
|
+
},
|
|
11
|
+
required: ['from', 'to'],
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'get_event',
|
|
16
|
+
description: 'Read one event on your calendar by id (from list_my_events or an invitation): when, where, description, organizer, every attendee and their answer.',
|
|
17
|
+
inputSchema: { type: 'object', properties: { id: { type: 'string', description: 'The event id.' } }, required: ['id'] },
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'respond_to_event',
|
|
21
|
+
description: 'Answer an invitation on your calendar: accepted, declined or tentative, with an optional comment for the organizer. The organizer sees your answer at once.',
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
id: { type: 'string', description: 'The event id.' },
|
|
26
|
+
response: { type: 'string', enum: ['accepted', 'declined', 'tentative'] },
|
|
27
|
+
comment: { type: 'string', description: 'Optional note to the organizer.' },
|
|
28
|
+
},
|
|
29
|
+
required: ['id', 'response'],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'find_free_time',
|
|
34
|
+
description: 'Find times when you and the attendees are all free for a meeting, between two times (at most 31 days apart), within working hours (09:00-17:00 Monday to Friday in timezone, UTC unless given). Members of the organization are checked on their calendars (busy times only); anyone whose calendar cannot be seen is listed as unknown. Longest free stretches first; a meeting fits anywhere inside one. Use it before proposing a time.',
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: {
|
|
38
|
+
duration_minutes: { type: 'number', description: 'How long the meeting is, in minutes.' },
|
|
39
|
+
from: { type: 'string', description: 'The earliest start, an ISO time.' },
|
|
40
|
+
to: { type: 'string', description: 'The latest end, an ISO time.' },
|
|
41
|
+
attendees: { type: 'array', items: { type: 'string' }, description: 'Email addresses of the others who should be free, e.g. ann@acme.freeflow.im.' },
|
|
42
|
+
timezone: { type: 'string', description: 'The IANA time zone working hours are in, e.g. America/New_York. Defaults to UTC.' },
|
|
43
|
+
working_hours: { type: 'string', description: 'HH:MM-HH:MM (default 09:00-17:00, Monday to Friday), or "any" for any time of any day.' },
|
|
44
|
+
},
|
|
45
|
+
required: ['duration_minutes', 'from', 'to'],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'create_event',
|
|
50
|
+
description: 'Book an event on your calendar and invite people by email address: members of the organization get it on their calendars at once and answer it there; anyone else is emailed an invitation where that is possible. Check find_free_time first, and say what you booked.',
|
|
51
|
+
inputSchema: {
|
|
52
|
+
type: 'object',
|
|
53
|
+
properties: {
|
|
54
|
+
summary: { type: 'string', description: 'The title.' },
|
|
55
|
+
start: { type: 'string', description: 'When it starts, an ISO time with a zone, e.g. 2026-12-03T15:00:00Z.' },
|
|
56
|
+
end: { type: 'string', description: 'When it ends, an ISO time.' },
|
|
57
|
+
attendees: { type: 'array', items: { type: 'string' }, description: 'Who to invite: "name@example.com" or "Name <name@example.com>".' },
|
|
58
|
+
location: { type: 'string', description: 'Where: an address or a link.' },
|
|
59
|
+
description: { type: 'string', description: 'Notes, plain text.' },
|
|
60
|
+
},
|
|
61
|
+
required: ['summary', 'start', 'end'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
export const CALENDAR_TOOL_NAMES = new Set(CALENDAR_TOOLS.map((t) => t.name));
|
|
66
|
+
/** When an event is, for a line or a prompt: "Thu, Dec 3, 2026, 15:00–16:00 UTC", or the day for an all-day one. */
|
|
67
|
+
export function whenOf(start, end, allDay) {
|
|
68
|
+
const day = (d) => new Intl.DateTimeFormat('en-US', { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', timeZone: 'UTC' }).format(d);
|
|
69
|
+
const s = new Date(start), e = new Date(end);
|
|
70
|
+
if (Number.isNaN(s.getTime()))
|
|
71
|
+
return start;
|
|
72
|
+
if (allDay)
|
|
73
|
+
return `${day(s)} (all day)`;
|
|
74
|
+
const time = (d) => d.toISOString().slice(11, 16);
|
|
75
|
+
return day(s) === day(e) ? `${day(s)}, ${time(s)}–${time(e)} UTC` : `${day(s)} ${time(s)} – ${day(e)} ${time(e)} UTC`;
|
|
76
|
+
}
|
|
77
|
+
const who = (p) => (p ? (p.name ? `${p.name} <${p.email}>` : p.email) : 'someone');
|
|
78
|
+
/** What the agent is asked when it is invited (the turn in the DM with the organizer, or the sponsor). */
|
|
79
|
+
export function invitationPrompt(d) {
|
|
80
|
+
const by = d.organizer ? `${d.organizer.name ? `${d.organizer.name} ` : ''}<${d.organizer.email}>` : 'someone';
|
|
81
|
+
return `You were invited to "${d.summary || 'an event'}" on ${whenOf(d.start, d.end, d.allDay)} by ${by}. ` +
|
|
82
|
+
'Decide whether to accept, decline or answer tentatively, and respond with the `respond_to_event` tool ' +
|
|
83
|
+
`(event id ${d.eventId}); you may ask a question in this DM first. get_event shows its details.`;
|
|
84
|
+
}
|
|
85
|
+
const line = (e) => `${e.id} ${whenOf(e.start, e.end, e.allDay)} ${e.summary || '(no title)'}${e.status === 'cancelled' ? ' (cancelled)' : ''}` +
|
|
86
|
+
`${e.organizer ? ` organizer ${who(e.organizer)}` : ''}${e.myResponse ? ` [your answer: ${e.myResponse}]` : ''}`;
|
|
87
|
+
const DAY = 86_400_000;
|
|
88
|
+
const EMAIL = /^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/;
|
|
89
|
+
/** "Name <a@b.c>" or "a@b.c" as the API's attendee, or null for something that is not an address. */
|
|
90
|
+
function personOf(s) {
|
|
91
|
+
const m = /^\s*(?:"?([^"<]*?)"?\s*)?<([^>]+)>\s*$/.exec(s);
|
|
92
|
+
const email = (m ? m[2] : s).trim().toLowerCase();
|
|
93
|
+
const name = m?.[1]?.trim();
|
|
94
|
+
return EMAIL.test(email) ? { email, ...(name ? { name } : {}) } : null;
|
|
95
|
+
}
|
|
96
|
+
/** How far `zone`'s wall clock is ahead of UTC at instant `t`. */
|
|
97
|
+
function offsetMs(t, zone) {
|
|
98
|
+
const parts = new Intl.DateTimeFormat('en-US', { timeZone: zone, hourCycle: 'h23', year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }).formatToParts(new Date(t));
|
|
99
|
+
const n = (k) => Number(parts.find((p) => p.type === k)?.value);
|
|
100
|
+
return Date.UTC(n('year'), n('month') - 1, n('day'), n('hour'), n('minute'), n('second')) - Math.floor(t / 1000) * 1000;
|
|
101
|
+
}
|
|
102
|
+
/** The instant a wall-clock time in `zone` names. */
|
|
103
|
+
function wallToUtc(y, mo, d, h, mi, zone) {
|
|
104
|
+
const guess = Date.UTC(y, mo - 1, d, h, mi);
|
|
105
|
+
const t = guess - offsetMs(guess, zone);
|
|
106
|
+
return guess - offsetMs(t, zone);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The free stretches of at least `durationMs` in [from, to) that no busy interval covers, within `hours` (wall-clock minutes
|
|
110
|
+
* from midnight, Monday to Friday) in `zone`, or at any time when `hours` is null: longest first, then earliest.
|
|
111
|
+
*/
|
|
112
|
+
export function freeStretches(busy, from, to, durationMs, hours, zone) {
|
|
113
|
+
const merged = [];
|
|
114
|
+
for (const [a, b] of busy.filter(([a, b]) => b > a).sort((x, y) => x[0] - y[0])) {
|
|
115
|
+
const last = merged.at(-1);
|
|
116
|
+
if (last && a <= last[1])
|
|
117
|
+
last[1] = Math.max(last[1], b);
|
|
118
|
+
else
|
|
119
|
+
merged.push([a, b]);
|
|
120
|
+
}
|
|
121
|
+
const windows = [];
|
|
122
|
+
if (!hours)
|
|
123
|
+
windows.push([from, to]);
|
|
124
|
+
else {
|
|
125
|
+
const first = new Date(from + offsetMs(from, zone));
|
|
126
|
+
for (let d = Date.UTC(first.getUTCFullYear(), first.getUTCMonth(), first.getUTCDate());; d += DAY) {
|
|
127
|
+
const day = new Date(d), y = day.getUTCFullYear(), mo = day.getUTCMonth() + 1, dd = day.getUTCDate();
|
|
128
|
+
const start = wallToUtc(y, mo, dd, Math.floor(hours[0] / 60), hours[0] % 60, zone);
|
|
129
|
+
if (start >= to)
|
|
130
|
+
break;
|
|
131
|
+
if (day.getUTCDay() === 0 || day.getUTCDay() === 6)
|
|
132
|
+
continue;
|
|
133
|
+
const a = Math.max(start, from), b = Math.min(wallToUtc(y, mo, dd, Math.floor(hours[1] / 60), hours[1] % 60, zone), to);
|
|
134
|
+
if (b > a)
|
|
135
|
+
windows.push([a, b]);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const out = [];
|
|
139
|
+
for (const [ws, we] of windows) {
|
|
140
|
+
let at = ws;
|
|
141
|
+
for (const [bs, be] of merged) {
|
|
142
|
+
if (be <= at || bs >= we)
|
|
143
|
+
continue;
|
|
144
|
+
if (bs - at >= durationMs)
|
|
145
|
+
out.push([at, bs]);
|
|
146
|
+
at = Math.max(at, be);
|
|
147
|
+
}
|
|
148
|
+
if (we - at >= durationMs)
|
|
149
|
+
out.push([at, we]);
|
|
150
|
+
}
|
|
151
|
+
return out.sort((x, y) => (y[1] - y[0]) - (x[1] - x[0]) || x[0] - y[0]);
|
|
152
|
+
}
|
|
153
|
+
/** One of CALENDAR_TOOLS, as the agent, in its organization: the text for the agent, and whether it is an error. */
|
|
154
|
+
export async function calendarTool(api, workspaceId, name, args) {
|
|
155
|
+
if (!workspaceId)
|
|
156
|
+
return { text: `${name} needs a workspace (FLOW_WORKSPACE_ID is not set)`, isError: true };
|
|
157
|
+
const id = typeof args.id === 'string' ? args.id.trim() : '';
|
|
158
|
+
try {
|
|
159
|
+
switch (name) {
|
|
160
|
+
case 'list_my_events': {
|
|
161
|
+
const from = String(args.from ?? '').trim(), to = String(args.to ?? '').trim();
|
|
162
|
+
if (!from || !to)
|
|
163
|
+
return { text: 'list_my_events needs from and to (ISO times)', isError: true };
|
|
164
|
+
const r = await api.calendar('GET', `events?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`, workspaceId);
|
|
165
|
+
return { text: r.events.length ? r.events.map(line).join('\n') : 'no events in that window', isError: false };
|
|
166
|
+
}
|
|
167
|
+
case 'get_event': {
|
|
168
|
+
if (!id)
|
|
169
|
+
return { text: 'get_event needs an id', isError: true };
|
|
170
|
+
const { event: e } = await api.calendar('GET', `events/${encodeURIComponent(id)}`, workspaceId);
|
|
171
|
+
const rows = [
|
|
172
|
+
line(e),
|
|
173
|
+
...(e.location ? [`where: ${e.location}`] : []),
|
|
174
|
+
...(e.description ? [`description: ${e.description.slice(0, 2000)}`] : []),
|
|
175
|
+
...(e.attendees?.length ? [`attendees: ${e.attendees.map((a) => `${who(a)} (${a.response ?? 'needs-action'})`).join(', ')}`] : []),
|
|
176
|
+
];
|
|
177
|
+
return { text: rows.join('\n'), isError: false };
|
|
178
|
+
}
|
|
179
|
+
case 'respond_to_event': {
|
|
180
|
+
const response = String(args.response ?? '');
|
|
181
|
+
if (!id || !['accepted', 'declined', 'tentative'].includes(response))
|
|
182
|
+
return { text: 'respond_to_event needs an id and a response: accepted, declined or tentative', isError: true };
|
|
183
|
+
const comment = typeof args.comment === 'string' && args.comment.trim() ? args.comment.trim().slice(0, 2000) : undefined;
|
|
184
|
+
const r = await api.calendar('POST', `events/${encodeURIComponent(id)}/respond`, workspaceId, { response, ...(comment ? { comment } : {}) });
|
|
185
|
+
const told = r.replied === 'failed' ? ` — but the organizer was not told: ${r.replyError ?? 'unknown error'}` : r.replied === 'none' ? '' : ' — the organizer has your answer';
|
|
186
|
+
return { text: `answered ${response} to "${r.event.summary}"${told}`, isError: r.replied === 'failed' };
|
|
187
|
+
}
|
|
188
|
+
case 'find_free_time': {
|
|
189
|
+
const minutes = Number(args.duration_minutes), from = Date.parse(String(args.from ?? '')), to = Date.parse(String(args.to ?? ''));
|
|
190
|
+
if (!(minutes >= 5 && minutes <= 1440) || Number.isNaN(from) || Number.isNaN(to) || to <= from)
|
|
191
|
+
return { text: 'find_free_time needs duration_minutes (5 to 1440) and from before to (ISO times)', isError: true };
|
|
192
|
+
if (to - from > 31 * DAY)
|
|
193
|
+
return { text: 'find_free_time looks at most 31 days at a time; ask in parts', isError: true };
|
|
194
|
+
const zone = typeof args.timezone === 'string' && args.timezone.trim() ? args.timezone.trim() : 'UTC';
|
|
195
|
+
try {
|
|
196
|
+
new Intl.DateTimeFormat('en-US', { timeZone: zone });
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return { text: `timezone: "${zone.slice(0, 60)}" is not an IANA time zone`, isError: true };
|
|
200
|
+
}
|
|
201
|
+
const wh = typeof args.working_hours === 'string' ? args.working_hours.trim() : '';
|
|
202
|
+
const m = /^(\d\d):(\d\d)-(\d\d):(\d\d)$/.exec(wh);
|
|
203
|
+
if (wh && wh !== 'any' && !m)
|
|
204
|
+
return { text: 'working_hours: HH:MM-HH:MM, or "any"', isError: true };
|
|
205
|
+
const hours = wh === 'any' ? null : m ? [Number(m[1]) * 60 + Number(m[2]), Number(m[3]) * 60 + Number(m[4])] : [9 * 60, 17 * 60];
|
|
206
|
+
const others = (Array.isArray(args.attendees) ? args.attendees : []).map((a) => personOf(String(a)));
|
|
207
|
+
if (others.some((p) => !p))
|
|
208
|
+
return { text: 'attendees: each one an email address', isError: true };
|
|
209
|
+
const window = { from: new Date(from).toISOString(), to: new Date(to).toISOString() };
|
|
210
|
+
// The agent's own busy time (no addresses: the server answers for the caller), and the attendees'.
|
|
211
|
+
const [mine, theirs] = await Promise.all([
|
|
212
|
+
api.calendar('POST', 'freebusy', workspaceId, { emails: [], ...window }),
|
|
213
|
+
others.length ? api.calendar('POST', 'freebusy', workspaceId, { emails: [...new Set(others.map((p) => p.email))], ...window }) : Promise.resolve({ busy: [], unknown: [] }),
|
|
214
|
+
]);
|
|
215
|
+
const busy = [...mine.busy, ...theirs.busy].flatMap((b) => b.intervals.map(([a, z]) => [Date.parse(a), Date.parse(z)]));
|
|
216
|
+
const slots = freeStretches(busy, from, to, minutes * 60_000, hours, zone).slice(0, 10);
|
|
217
|
+
const iso = (t) => new Date(t).toISOString().replace(':00.000Z', 'Z');
|
|
218
|
+
const rows = [
|
|
219
|
+
...(slots.length ? slots.map(([a, b]) => `${iso(a)} – ${iso(b)} (${Math.round((b - a) / 60_000)} min)`) : ['no free time of that length in the window']),
|
|
220
|
+
`working hours: ${hours ? `${wh && wh !== 'any' ? wh : '09:00-17:00'} Mon-Fri ${zone}` : 'any time'}`,
|
|
221
|
+
...(theirs.busy.length ? [`checked: ${theirs.busy.map((b) => b.email).join(', ')}`] : []),
|
|
222
|
+
...(theirs.unknown.length ? [`unknown (their calendars cannot be seen; say so when proposing a time): ${theirs.unknown.join(', ')}`] : []),
|
|
223
|
+
];
|
|
224
|
+
return { text: rows.join('\n'), isError: false };
|
|
225
|
+
}
|
|
226
|
+
case 'create_event': {
|
|
227
|
+
const summary = String(args.summary ?? '').trim(), start = String(args.start ?? '').trim(), end = String(args.end ?? '').trim();
|
|
228
|
+
if (!summary || !start || !end)
|
|
229
|
+
return { text: 'create_event needs summary, start and end', isError: true };
|
|
230
|
+
const attendees = (Array.isArray(args.attendees) ? args.attendees : []).map((a) => personOf(String(a)));
|
|
231
|
+
if (attendees.some((p) => !p))
|
|
232
|
+
return { text: 'attendees: each one "name@example.com" or "Name <name@example.com>"', isError: true };
|
|
233
|
+
const body = {
|
|
234
|
+
summary, start, end,
|
|
235
|
+
...(attendees.length ? { attendees } : {}),
|
|
236
|
+
...(typeof args.location === 'string' && args.location.trim() ? { location: args.location.trim().slice(0, 2000) } : {}),
|
|
237
|
+
...(typeof args.description === 'string' && args.description.trim() ? { description: args.description.slice(0, 32_000) } : {}),
|
|
238
|
+
};
|
|
239
|
+
const r = await api.calendar('POST', 'events', workspaceId, body);
|
|
240
|
+
const e = r.event;
|
|
241
|
+
const guests = (e.attendees ?? []).filter((a) => !a.self && a.email !== e.organizer?.email);
|
|
242
|
+
const members = guests.filter((a) => a.accountId).map((a) => a.email), outside = guests.filter((a) => !a.accountId).map((a) => a.email);
|
|
243
|
+
const rows = [
|
|
244
|
+
`created ${line(e)}`,
|
|
245
|
+
...(members.length ? [`on their calendars now: ${members.join(', ')}`] : []),
|
|
246
|
+
...(outside.length ? [r.invitationsSent === false ? `not emailed: ${outside.join(', ')}${r.invitationsNote ? ` (${r.invitationsNote})` : ''}` : `emailed an invitation: ${outside.join(', ')}`] : []),
|
|
247
|
+
];
|
|
248
|
+
return { text: rows.join('\n'), isError: false };
|
|
249
|
+
}
|
|
250
|
+
default:
|
|
251
|
+
return { text: `unknown tool: ${name}`, isError: true };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
catch (err) {
|
|
255
|
+
return { text: `${name} failed: ${err.message}`, isError: true };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=calendar-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-tools.js","sourceRoot":"","sources":["../src/calendar-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { DeliveryMode, Event, EventFilter, PlatformEvent, SubscriptionDTO } from '@flow/shared';
|
|
2
|
+
import type { FlowApi } from './api.js';
|
|
3
|
+
export declare const CATCH_UP_TYPES: string[];
|
|
4
|
+
/** The events addressed to the agent's account alone that ask it for a turn: the job subscription's, and what `onAccount` gets. */
|
|
5
|
+
export declare const ACCOUNT_TYPES: string[];
|
|
6
|
+
/** How many answered message ids are remembered. */
|
|
7
|
+
export declare const HANDLED_MAX = 500;
|
|
8
|
+
export type SubscriptionApi = Pick<FlowApi, 'listSubscriptions' | 'createSubscription' | 'readSubscription' | 'ackSubscription'>;
|
|
9
|
+
export declare const subscriptionName: (agentId: string) => string;
|
|
10
|
+
export declare const jobsSubscriptionName: (agentId: string) => string;
|
|
11
|
+
export interface SubscriptionSpec {
|
|
12
|
+
name: string;
|
|
13
|
+
filter: EventFilter;
|
|
14
|
+
delivery: DeliveryMode;
|
|
15
|
+
}
|
|
16
|
+
/** The live path for jobs and invitations: a poke on the socket when an `agent.job` or `calendar.invited` for this account comes. */
|
|
17
|
+
export declare const jobsSpec: (agentId: string) => SubscriptionSpec;
|
|
18
|
+
/**
|
|
19
|
+
* The bridge's subscription in the organization: found by name, or made (starting at the log's head). `outdated` when
|
|
20
|
+
* one made by an older bridge lists types without some of today's (`agent.job`): it is caught up, then replaced.
|
|
21
|
+
*/
|
|
22
|
+
export declare function ensureSubscription(api: SubscriptionApi, workspaceId: string, agentId: string, spec?: SubscriptionSpec): Promise<SubscriptionDTO & {
|
|
23
|
+
outdated?: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Reads the subscription without waiting, page by page until it is empty, handing each Chat event to `feed` in order
|
|
27
|
+
* (and each of ACCOUNT_TYPES to `onJob`) and acking each page's `next` once its events are fed. Returns the events fed
|
|
28
|
+
* and the cursor reached.
|
|
29
|
+
*/
|
|
30
|
+
export declare function catchUp(api: SubscriptionApi, workspaceId: string, sub: Pick<SubscriptionDTO, 'id' | 'cursor'>, feed: (event: Event) => Promise<void> | void, log: (msg: string) => void, onJob?: (event: PlatformEvent) => Promise<void> | void): Promise<{
|
|
31
|
+
events: number;
|
|
32
|
+
next: number;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* The ids of the last messages the bridge answered (or, with `key: 'handledJobIds'`, the wake jobs it took), oldest
|
|
36
|
+
* first, kept in `file` (when given) across restarts. Each set has its key in the file and leaves the others' alone.
|
|
37
|
+
*/
|
|
38
|
+
export declare class HandledMessages {
|
|
39
|
+
private readonly file;
|
|
40
|
+
private readonly log;
|
|
41
|
+
private readonly max;
|
|
42
|
+
private readonly key;
|
|
43
|
+
private readonly ids;
|
|
44
|
+
private readonly set;
|
|
45
|
+
constructor(file: string | null, log?: (msg: string) => void, max?: number, key?: string);
|
|
46
|
+
has(id: string): boolean;
|
|
47
|
+
/** Remembers `id` and writes the file. False when it was already there. */
|
|
48
|
+
add(id: string): boolean;
|
|
49
|
+
private remember;
|
|
50
|
+
}
|
package/dist/catch-up.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Catching up after being offline (platform.md §5.2, phase 2.3). The bridge keeps one subscription per organization it
|
|
2
|
+
// serves, `bridge:<agent user id>`, on the events that can ask it for a turn. At start it reads what the subscription
|
|
3
|
+
// holds before opening the socket, feeding each event through the path live events take, and acks as it goes; while
|
|
4
|
+
// connected it acks the socket's latest cursor, so the next start replays only what was missed. The subscription is the
|
|
5
|
+
// catch-up path, not a filter: what gets answered is still `addressedToMe`'s call. A small set of answered message ids,
|
|
6
|
+
// kept in a state file beside the config, makes sure no message is answered twice across a restart.
|
|
7
|
+
// Wake jobs (phase 2.4) arrive as `agent.job` events on the agent's own account: the subscription catches up on them too,
|
|
8
|
+
// and a second one, `bridge-jobs:<agent id>` with `socket` delivery, pokes the socket when one comes while connected.
|
|
9
|
+
// Job ids taken are remembered in the same state file, so a job is run once. Invitations (phase 4.2) come the same way:
|
|
10
|
+
// `calendar.invited` on the agent's own account, in both subscriptions, each event id answered once (state file too).
|
|
11
|
+
import fs from 'node:fs';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { socketEventOf } from './gateway.js';
|
|
14
|
+
export const CATCH_UP_TYPES = ['chat.message.created', 'chat.thread.reply', 'chat.reaction.added', 'agent.job', 'calendar.invited'];
|
|
15
|
+
/** The events addressed to the agent's account alone that ask it for a turn: the job subscription's, and what `onAccount` gets. */
|
|
16
|
+
export const ACCOUNT_TYPES = ['agent.job', 'calendar.invited'];
|
|
17
|
+
/** How many answered message ids are remembered. */
|
|
18
|
+
export const HANDLED_MAX = 500;
|
|
19
|
+
/** A bound on one catch-up's pages, so a server that never runs dry cannot hold the start-up forever. */
|
|
20
|
+
const MAX_PAGES = 100;
|
|
21
|
+
export const subscriptionName = (agentId) => `bridge:${agentId}`;
|
|
22
|
+
export const jobsSubscriptionName = (agentId) => `bridge-jobs:${agentId}`;
|
|
23
|
+
const mainSpec = (agentId) => ({ name: subscriptionName(agentId), filter: { types: CATCH_UP_TYPES }, delivery: 'pull' });
|
|
24
|
+
/** The live path for jobs and invitations: a poke on the socket when an `agent.job` or `calendar.invited` for this account comes. */
|
|
25
|
+
export const jobsSpec = (agentId) => ({ name: jobsSubscriptionName(agentId), filter: { types: ACCOUNT_TYPES, self: true }, delivery: 'socket' });
|
|
26
|
+
/**
|
|
27
|
+
* The bridge's subscription in the organization: found by name, or made (starting at the log's head). `outdated` when
|
|
28
|
+
* one made by an older bridge lists types without some of today's (`agent.job`): it is caught up, then replaced.
|
|
29
|
+
*/
|
|
30
|
+
export async function ensureSubscription(api, workspaceId, agentId, spec = mainSpec(agentId)) {
|
|
31
|
+
const found = (await api.listSubscriptions(workspaceId)).find((s) => s.name === spec.name && s.consumer === s.owner);
|
|
32
|
+
if (found) {
|
|
33
|
+
const want = spec.filter.types ?? [];
|
|
34
|
+
const types = found.filter.types;
|
|
35
|
+
return types && want.some((t) => !types.includes(t)) ? { ...found, outdated: true } : found;
|
|
36
|
+
}
|
|
37
|
+
return api.createSubscription(workspaceId, spec);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Reads the subscription without waiting, page by page until it is empty, handing each Chat event to `feed` in order
|
|
41
|
+
* (and each of ACCOUNT_TYPES to `onJob`) and acking each page's `next` once its events are fed. Returns the events fed
|
|
42
|
+
* and the cursor reached.
|
|
43
|
+
*/
|
|
44
|
+
export async function catchUp(api, workspaceId, sub, feed, log, onJob) {
|
|
45
|
+
let cursor = sub.cursor;
|
|
46
|
+
let events = 0;
|
|
47
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
48
|
+
const out = await api.readSubscription(workspaceId, sub.id, { wait: 0 });
|
|
49
|
+
if (out.gap)
|
|
50
|
+
log(`catch-up: events ${out.gap.from}–${out.gap.to} aged out of the log before they were read`);
|
|
51
|
+
for (const e of out.events) {
|
|
52
|
+
const event = socketEventOf(e);
|
|
53
|
+
if (!event && !(ACCOUNT_TYPES.includes(e.type) && onJob))
|
|
54
|
+
continue;
|
|
55
|
+
events++;
|
|
56
|
+
try {
|
|
57
|
+
if (event)
|
|
58
|
+
await feed(event);
|
|
59
|
+
else
|
|
60
|
+
await onJob(e);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
log(`catch-up: event ${e.seq} (${e.type}) failed: ${err.message}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (out.next > cursor)
|
|
67
|
+
cursor = await api.ackSubscription(workspaceId, sub.id, out.next);
|
|
68
|
+
if (!out.events.length)
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
return { events, next: cursor };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The ids of the last messages the bridge answered (or, with `key: 'handledJobIds'`, the wake jobs it took), oldest
|
|
75
|
+
* first, kept in `file` (when given) across restarts. Each set has its key in the file and leaves the others' alone.
|
|
76
|
+
*/
|
|
77
|
+
export class HandledMessages {
|
|
78
|
+
file;
|
|
79
|
+
log;
|
|
80
|
+
max;
|
|
81
|
+
key;
|
|
82
|
+
ids = [];
|
|
83
|
+
set = new Set();
|
|
84
|
+
constructor(file, log = () => { }, max = HANDLED_MAX, key = 'handledMessageIds') {
|
|
85
|
+
this.file = file;
|
|
86
|
+
this.log = log;
|
|
87
|
+
this.max = max;
|
|
88
|
+
this.key = key;
|
|
89
|
+
if (!file)
|
|
90
|
+
return;
|
|
91
|
+
try {
|
|
92
|
+
const raw = JSON.parse(fs.readFileSync(file, 'utf8'))[key];
|
|
93
|
+
const ids = Array.isArray(raw) ? raw.filter((x) => typeof x === 'string') : [];
|
|
94
|
+
for (const id of ids.slice(-max))
|
|
95
|
+
this.remember(id);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
if (err.code !== 'ENOENT')
|
|
99
|
+
log(`state file ${file} unreadable (${err.message}) — starting empty`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
has(id) {
|
|
103
|
+
return this.set.has(id);
|
|
104
|
+
}
|
|
105
|
+
/** Remembers `id` and writes the file. False when it was already there. */
|
|
106
|
+
add(id) {
|
|
107
|
+
if (this.set.has(id))
|
|
108
|
+
return false;
|
|
109
|
+
this.remember(id);
|
|
110
|
+
if (this.file) {
|
|
111
|
+
try {
|
|
112
|
+
fs.mkdirSync(path.dirname(this.file), { recursive: true });
|
|
113
|
+
const tmp = `${this.file}.tmp`;
|
|
114
|
+
let all = {};
|
|
115
|
+
try {
|
|
116
|
+
all = JSON.parse(fs.readFileSync(this.file, 'utf8'));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
/* none yet, or unreadable: this set starts the file */
|
|
120
|
+
}
|
|
121
|
+
fs.writeFileSync(tmp, JSON.stringify({ ...all, [this.key]: this.ids }), { mode: 0o600 });
|
|
122
|
+
fs.renameSync(tmp, this.file);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
this.log(`state file ${this.file} not written: ${err.message}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
remember(id) {
|
|
131
|
+
this.ids.push(id);
|
|
132
|
+
this.set.add(id);
|
|
133
|
+
while (this.ids.length > this.max)
|
|
134
|
+
this.set.delete(this.ids.shift());
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=catch-up.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catch-up.js","sourceRoot":"","sources":["../src/catch-up.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -127,7 +127,16 @@ export interface BridgeConfig {
|
|
|
127
127
|
/** Live audio in the existing Flow Huddle. Optional for source-level
|
|
128
128
|
* callers that construct BridgeConfig directly; loadConfig always fills it. */
|
|
129
129
|
voice?: VoiceConfig | undefined;
|
|
130
|
+
/**
|
|
131
|
+
* What the bridge remembers across restarts: the ids of the last messages it
|
|
132
|
+
* answered, so a catch-up after a restart never answers one twice. Beside the
|
|
133
|
+
* config (agent.json → state.json, other.json → other.state.json); absent or
|
|
134
|
+
* null keeps it in memory only.
|
|
135
|
+
*/
|
|
136
|
+
stateFile?: string | null;
|
|
130
137
|
}
|
|
138
|
+
/** The state file beside a config: `state.json` for `agent.json`, else `<name>.state.json`. */
|
|
139
|
+
export declare function stateFileFor(configPath: string): string;
|
|
131
140
|
export declare function loadConfig(configPath: string): BridgeConfig;
|
|
132
141
|
/**
|
|
133
142
|
* The effective mention limit: unset means 4× the chain limit, 0 means the
|
package/dist/config.js
CHANGED
|
@@ -20,6 +20,12 @@ export function defaultVoiceConfig() {
|
|
|
20
20
|
maxSessionMinutes: 60,
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
+
/** The state file beside a config: `state.json` for `agent.json`, else `<name>.state.json`. */
|
|
24
|
+
export function stateFileFor(configPath) {
|
|
25
|
+
const abs = path.resolve(configPath);
|
|
26
|
+
const base = path.basename(abs).replace(/\.json$/i, '');
|
|
27
|
+
return path.join(path.dirname(abs), base === 'agent' ? 'state.json' : `${base}.state.json`);
|
|
28
|
+
}
|
|
23
29
|
export function loadConfig(configPath) {
|
|
24
30
|
const abs = path.resolve(configPath);
|
|
25
31
|
let raw;
|
|
@@ -116,6 +122,7 @@ export function loadConfig(configPath) {
|
|
|
116
122
|
progress,
|
|
117
123
|
relayText: raw.relayText ?? true,
|
|
118
124
|
voice,
|
|
125
|
+
stateFile: stateFileFor(abs),
|
|
119
126
|
};
|
|
120
127
|
}
|
|
121
128
|
/**
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,yEAAyE;AACzE,qDAAqD;AACrD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,mGAAmG;AACnG,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,IAAI,CAAC,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC;IACnC,OAAO,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC;AAuBD,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,0BAA0B;QAChF,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,uBAAuB;QAC7E,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,QAAQ;QAC9D,YAAY,EACV,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,EAAE,IAAI,wCAAwC;QAC1F,iBAAiB,EAAE,EAAE;KACtB,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/gateway.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type { Event } from '@flow/shared';
|
|
1
|
+
import type { Event, PlatformEvent } from '@flow/shared';
|
|
2
|
+
/**
|
|
3
|
+
* A logged event (platform.md §5.2) as the socket event it was: Chat's `chat.<type>` back to `<type>`, with the row's
|
|
4
|
+
* channel, time and data. Events of other apps (`mail.*`) are not socket events: null.
|
|
5
|
+
*/
|
|
6
|
+
export declare function socketEventOf(e: PlatformEvent): Event | null;
|
|
2
7
|
export interface FlowSocketOpts {
|
|
3
8
|
serverUrl: string;
|
|
4
9
|
token: string;
|
|
@@ -12,12 +17,23 @@ export interface FlowSocketOpts {
|
|
|
12
17
|
log(msg: string): void;
|
|
13
18
|
/** On a server with one socket per organization, the one this socket serves. */
|
|
14
19
|
organization?: string;
|
|
20
|
+
/**
|
|
21
|
+
* The event log's seq to replay from on the first connect (`auth` with `since`, platform.md §5.2); later reconnects
|
|
22
|
+
* send the latest `cursor` frame instead. Unset and no cursor yet: no replay.
|
|
23
|
+
*/
|
|
24
|
+
since?: number;
|
|
25
|
+
/** The log reached `seq` and every event so far has been handed to `onEvent`. */
|
|
26
|
+
onCursor?(seq: number): void;
|
|
27
|
+
/** A `socket` subscription of this account has new events (platform.md §5.2): read it over HTTP. */
|
|
28
|
+
onSubscription?(id: string): void;
|
|
15
29
|
}
|
|
16
30
|
export declare class FlowSocket {
|
|
17
31
|
private readonly opts;
|
|
18
32
|
private ws;
|
|
19
33
|
private closed;
|
|
20
34
|
private attempt;
|
|
35
|
+
/** The last log seq this socket has handed on: sent as `since` on every connect, so a drop loses nothing. */
|
|
36
|
+
private cursor;
|
|
21
37
|
constructor(opts: FlowSocketOpts);
|
|
22
38
|
connect(): void;
|
|
23
39
|
private scheduleReconnect;
|