@agentdeck/bridge 1.0.4 → 1.0.5
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/assets/fm-helper/agentdeck-fm-helper +0 -0
- package/dist/adapters/claude-code.d.ts.map +1 -1
- package/dist/adapters/claude-code.js +3 -0
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/adb-reverse.d.ts.map +1 -1
- package/dist/adb-reverse.js +4 -2
- package/dist/adb-reverse.js.map +1 -1
- package/dist/apme/collector.js +2 -2
- package/dist/apme/collector.js.map +1 -1
- package/dist/apme/outcome.js +2 -2
- package/dist/apme/outcome.js.map +1 -1
- package/dist/apme/runner.js +3 -3
- package/dist/apme/runner.js.map +1 -1
- package/dist/ble-sync-spawn.js +1 -1
- package/dist/ble-sync-spawn.js.map +1 -1
- package/dist/calendar.d.ts +82 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +324 -0
- package/dist/calendar.js.map +1 -0
- package/dist/card-feed.d.ts +63 -5
- package/dist/card-feed.d.ts.map +1 -1
- package/dist/card-feed.js +218 -14
- package/dist/card-feed.js.map +1 -1
- package/dist/card-modules.d.ts +4 -0
- package/dist/card-modules.d.ts.map +1 -1
- package/dist/card-modules.js +5 -3
- package/dist/card-modules.js.map +1 -1
- package/dist/check-deps.js +4 -4
- package/dist/check-deps.js.map +1 -1
- package/dist/cli.d.ts +35 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +269 -9
- package/dist/cli.js.map +1 -1
- package/dist/codex-otel.d.ts +89 -0
- package/dist/codex-otel.d.ts.map +1 -0
- package/dist/codex-otel.js +487 -0
- package/dist/codex-otel.js.map +1 -0
- package/dist/codex-rate-limits.d.ts.map +1 -1
- package/dist/codex-rate-limits.js +15 -3
- package/dist/codex-rate-limits.js.map +1 -1
- package/dist/daemon-server.d.ts +4 -0
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +797 -54
- package/dist/daemon-server.js.map +1 -1
- package/dist/daemon-ws-client.d.ts +108 -24
- package/dist/daemon-ws-client.d.ts.map +1 -1
- package/dist/daemon-ws-client.js +175 -39
- package/dist/daemon-ws-client.js.map +1 -1
- package/dist/daemon.js +1 -1
- package/dist/device-voice-reply.d.ts.map +1 -1
- package/dist/device-voice-reply.js +15 -3
- package/dist/device-voice-reply.js.map +1 -1
- package/dist/device-voice.d.ts +37 -0
- package/dist/device-voice.d.ts.map +1 -1
- package/dist/device-voice.js +130 -1
- package/dist/device-voice.js.map +1 -1
- package/dist/diag-analyzer.d.ts.map +1 -1
- package/dist/diag-analyzer.js +1 -0
- package/dist/diag-analyzer.js.map +1 -1
- package/dist/display-monitor.d.ts.map +1 -1
- package/dist/display-monitor.js +1 -0
- package/dist/display-monitor.js.map +1 -1
- package/dist/esp32-serial.d.ts +4 -0
- package/dist/esp32-serial.d.ts.map +1 -1
- package/dist/esp32-serial.js +6 -3
- package/dist/esp32-serial.js.map +1 -1
- package/dist/foundation-models-helper.d.ts +23 -0
- package/dist/foundation-models-helper.d.ts.map +1 -1
- package/dist/foundation-models-helper.js +32 -0
- package/dist/foundation-models-helper.js.map +1 -1
- package/dist/gateway-probe.js +1 -1
- package/dist/gateway-probe.js.map +1 -1
- package/dist/glance-frame.d.ts +64 -0
- package/dist/glance-frame.d.ts.map +1 -0
- package/dist/glance-frame.js +364 -0
- package/dist/glance-frame.js.map +1 -0
- package/dist/hook-codex-sessions.d.ts +40 -0
- package/dist/hook-codex-sessions.d.ts.map +1 -0
- package/dist/hook-codex-sessions.js +174 -0
- package/dist/hook-codex-sessions.js.map +1 -0
- package/dist/idotmatrix/idotmatrix-discover.d.ts.map +1 -1
- package/dist/idotmatrix/idotmatrix-discover.js +7 -4
- package/dist/idotmatrix/idotmatrix-discover.js.map +1 -1
- package/dist/idotmatrix/idotmatrix-settings.d.ts +15 -0
- package/dist/idotmatrix/idotmatrix-settings.d.ts.map +1 -1
- package/dist/idotmatrix/idotmatrix-settings.js +21 -0
- package/dist/idotmatrix/idotmatrix-settings.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +88 -7
- package/dist/index.js.map +1 -1
- package/dist/linux-service.d.ts +52 -0
- package/dist/linux-service.d.ts.map +1 -0
- package/dist/linux-service.js +206 -0
- package/dist/linux-service.js.map +1 -0
- package/dist/logger.d.ts +6 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +15 -0
- package/dist/logger.js.map +1 -1
- package/dist/mdns-discover.d.ts +19 -0
- package/dist/mdns-discover.d.ts.map +1 -0
- package/dist/mdns-discover.js +109 -0
- package/dist/mdns-discover.js.map +1 -0
- package/dist/model-catalog.d.ts.map +1 -1
- package/dist/model-catalog.js +1 -0
- package/dist/model-catalog.js.map +1 -1
- package/dist/modules/adb-module.js +1 -1
- package/dist/modules/adb-module.js.map +1 -1
- package/dist/output-parser.d.ts +9 -0
- package/dist/output-parser.d.ts.map +1 -1
- package/dist/output-parser.js +67 -16
- package/dist/output-parser.js.map +1 -1
- package/dist/passive-observer.d.ts +57 -8
- package/dist/passive-observer.d.ts.map +1 -1
- package/dist/passive-observer.js +210 -74
- package/dist/passive-observer.js.map +1 -1
- package/dist/pixoo/pixoo-bridge.d.ts.map +1 -1
- package/dist/pixoo/pixoo-bridge.js +47 -6
- package/dist/pixoo/pixoo-bridge.js.map +1 -1
- package/dist/pixoo/pixoo-renderer.d.ts +2 -1
- package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
- package/dist/pixoo/pixoo-renderer.js +137 -8
- package/dist/pixoo/pixoo-renderer.js.map +1 -1
- package/dist/pocket-autonomy.d.ts +78 -0
- package/dist/pocket-autonomy.d.ts.map +1 -0
- package/dist/pocket-autonomy.js +529 -0
- package/dist/pocket-autonomy.js.map +1 -0
- package/dist/pty-manager.d.ts.map +1 -1
- package/dist/pty-manager.js +3 -2
- package/dist/pty-manager.js.map +1 -1
- package/dist/python-ble-runtime.d.ts +2 -0
- package/dist/python-ble-runtime.d.ts.map +1 -1
- package/dist/python-ble-runtime.js +2 -1
- package/dist/python-ble-runtime.js.map +1 -1
- package/dist/remote-sessions.d.ts +64 -0
- package/dist/remote-sessions.d.ts.map +1 -0
- package/dist/remote-sessions.js +81 -0
- package/dist/remote-sessions.js.map +1 -0
- package/dist/review-runner.js +2 -2
- package/dist/review-runner.js.map +1 -1
- package/dist/session-aggregator.d.ts +2 -0
- package/dist/session-aggregator.d.ts.map +1 -1
- package/dist/session-aggregator.js +6 -1
- package/dist/session-aggregator.js.map +1 -1
- package/dist/session-focus-relay.d.ts +47 -1
- package/dist/session-focus-relay.d.ts.map +1 -1
- package/dist/session-focus-relay.js +130 -15
- package/dist/session-focus-relay.js.map +1 -1
- package/dist/session-push-channel.d.ts +31 -0
- package/dist/session-push-channel.d.ts.map +1 -0
- package/dist/session-push-channel.js +94 -0
- package/dist/session-push-channel.js.map +1 -0
- package/dist/session-registry.d.ts +126 -0
- package/dist/session-registry.d.ts.map +1 -1
- package/dist/session-registry.js +180 -3
- package/dist/session-registry.js.map +1 -1
- package/dist/subagent-timeline.d.ts +34 -0
- package/dist/subagent-timeline.d.ts.map +1 -0
- package/dist/subagent-timeline.js +156 -0
- package/dist/subagent-timeline.js.map +1 -0
- package/dist/timebox/timebox-discover.js +1 -1
- package/dist/timebox/timebox-discover.js.map +1 -1
- package/dist/tui/gauge.d.ts +4 -2
- package/dist/tui/gauge.d.ts.map +1 -1
- package/dist/tui/gauge.js +8 -4
- package/dist/tui/gauge.js.map +1 -1
- package/dist/tui/renderer.d.ts.map +1 -1
- package/dist/tui/renderer.js +28 -0
- package/dist/tui/renderer.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/usage-api.d.ts +43 -0
- package/dist/usage-api.d.ts.map +1 -1
- package/dist/usage-api.js +114 -9
- package/dist/usage-api.js.map +1 -1
- package/dist/usage-event.d.ts +19 -0
- package/dist/usage-event.d.ts.map +1 -1
- package/dist/usage-event.js +35 -0
- package/dist/usage-event.js.map +1 -1
- package/dist/utils/project-name.d.ts.map +1 -1
- package/dist/utils/project-name.js +1 -0
- package/dist/utils/project-name.js.map +1 -1
- package/dist/version-check.d.ts.map +1 -1
- package/dist/version-check.js +3 -2
- package/dist/version-check.js.map +1 -1
- package/dist/voice-assistant.d.ts.map +1 -1
- package/dist/voice-assistant.js +2 -1
- package/dist/voice-assistant.js.map +1 -1
- package/dist/voice.d.ts.map +1 -1
- package/dist/voice.js +1 -0
- package/dist/voice.js.map +1 -1
- package/dist/weather.d.ts +72 -0
- package/dist/weather.d.ts.map +1 -0
- package/dist/weather.js +206 -0
- package/dist/weather.js.map +1 -0
- package/dist/windows-service.js +5 -5
- package/dist/windows-service.js.map +1 -1
- package/fm-helper/AgentDeckFMHelper.swift +200 -0
- package/package.json +15 -13
- package/src/idotmatrix/identity_generated.py +50 -0
- package/src/idotmatrix/scan.py +33 -13
package/dist/calendar.js
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Glance schedule provider (ICS) — daemon-side module for the card-feed sleep
|
|
3
|
+
* dashboard (M9 stage 2). The device never parses a calendar itself; the
|
|
4
|
+
* daemon fetches the ICS feed(s), expands today's occurrences, and pre-renders
|
|
5
|
+
* them into `CardFeedResponse.glance.events` (shared/src/protocol.ts § Glance).
|
|
6
|
+
*
|
|
7
|
+
* Config comes from settings.json — one secret-address ICS URL (Google
|
|
8
|
+
* Calendar / iCloud / Fastmail all export one) or a list:
|
|
9
|
+
*
|
|
10
|
+
* "calendar": { "ics": "https://calendar.google.com/calendar/ical/…/basic.ics" }
|
|
11
|
+
* "calendar": { "ics": ["https://…/basic.ics", "https://…/work.ics"] }
|
|
12
|
+
*
|
|
13
|
+
* No config → no schedule in the glance (never a guess).
|
|
14
|
+
*
|
|
15
|
+
* Deliberately dependency-free, like weather.ts. The parser covers the ICS
|
|
16
|
+
* subset a personal "what's left of today" needs:
|
|
17
|
+
* - VEVENT with SUMMARY / DTSTART / DTEND, line unfolding, text unescaping
|
|
18
|
+
* - all-day events (VALUE=DATE), UTC instants (…Z), floating/TZID-local
|
|
19
|
+
* times (TZID is assumed to be the daemon's own zone — the common case for
|
|
20
|
+
* a personal calendar; a cross-zone TZID renders at its literal HH:MM)
|
|
21
|
+
* - RRULE FREQ=DAILY/WEEKLY(BYDAY)/MONTHLY(BYMONTHDAY)/YEARLY with
|
|
22
|
+
* INTERVAL / UNTIL / COUNT, expanded by bounded day-walk from DTSTART
|
|
23
|
+
* - EXDATE and RECURRENCE-ID overrides (override replaces that instance)
|
|
24
|
+
*/
|
|
25
|
+
import { GLANCE_MAX_EVENTS, GLANCE_EVENT_TITLE_MAX_BYTES } from '@agentdeck/shared';
|
|
26
|
+
import { trimUtf8Bytes } from './card-feed.js';
|
|
27
|
+
/** Serve from cache inside this window — schedule cadence is slower than the
|
|
28
|
+
* fastest pull cadence (900s). */
|
|
29
|
+
export const CALENDAR_CACHE_MS = 30 * 60 * 1000;
|
|
30
|
+
/** After a fetch failure, keep serving the last good parse up to this age. */
|
|
31
|
+
export const CALENDAR_STALE_SERVE_MS = 6 * 60 * 60 * 1000;
|
|
32
|
+
/** External peer await — timeout is first-line, not optional. */
|
|
33
|
+
export const CALENDAR_FETCH_TIMEOUT_MS = 8000;
|
|
34
|
+
/** Recurrence day-walk bound (~10 years) — a runaway RRULE must terminate. */
|
|
35
|
+
const MAX_RECURRENCE_WALK_DAYS = 3700;
|
|
36
|
+
export function parseCalendarSettings(settings) {
|
|
37
|
+
const c = settings?.calendar;
|
|
38
|
+
if (!c || typeof c !== 'object')
|
|
39
|
+
return null;
|
|
40
|
+
const raw = c.ics;
|
|
41
|
+
const urls = (Array.isArray(raw) ? raw : [raw])
|
|
42
|
+
.filter((u) => typeof u === 'string' && /^https?:\/\//.test(u));
|
|
43
|
+
return urls.length > 0 ? { urls } : null;
|
|
44
|
+
}
|
|
45
|
+
/** RFC 5545 line unfolding: CRLF followed by space/tab continues the line. */
|
|
46
|
+
export function unfoldIcsLines(text) {
|
|
47
|
+
const raw = text.split(/\r?\n/);
|
|
48
|
+
const out = [];
|
|
49
|
+
for (const line of raw) {
|
|
50
|
+
if ((line.startsWith(' ') || line.startsWith('\t')) && out.length > 0) {
|
|
51
|
+
out[out.length - 1] += line.slice(1);
|
|
52
|
+
}
|
|
53
|
+
else if (line.length > 0) {
|
|
54
|
+
out.push(line);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
function unescapeIcsText(s) {
|
|
60
|
+
return s.replace(/\\n/gi, ' ').replace(/\\([,;\\])/g, '$1');
|
|
61
|
+
}
|
|
62
|
+
const pad2 = (n) => String(n).padStart(2, '0');
|
|
63
|
+
const dateKey = (d) => `${d.getFullYear()}${pad2(d.getMonth() + 1)}${pad2(d.getDate())}`;
|
|
64
|
+
const hmKey = (d) => `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
|
|
65
|
+
/** One DTSTART/DTEND/EXDATE value → local date + optional HH:MM.
|
|
66
|
+
* `…Z` converts through the daemon clock; floating/TZID read literally. */
|
|
67
|
+
export function parseIcsInstant(value) {
|
|
68
|
+
const m = value.match(/^(\d{8})(?:T(\d{2})(\d{2})(\d{2})?(Z)?)?$/);
|
|
69
|
+
if (!m)
|
|
70
|
+
return null;
|
|
71
|
+
const [, ymd, hh, mm, , zulu] = m;
|
|
72
|
+
if (!hh)
|
|
73
|
+
return { date: ymd };
|
|
74
|
+
if (zulu) {
|
|
75
|
+
const d = new Date(Date.UTC(Number(ymd.slice(0, 4)), Number(ymd.slice(4, 6)) - 1, Number(ymd.slice(6, 8)), Number(hh), Number(mm)));
|
|
76
|
+
return { date: dateKey(d), hm: hmKey(d) };
|
|
77
|
+
}
|
|
78
|
+
return { date: ymd, hm: `${hh}:${mm}` };
|
|
79
|
+
}
|
|
80
|
+
export function parseIcsEvents(text) {
|
|
81
|
+
const events = [];
|
|
82
|
+
let cur = null;
|
|
83
|
+
for (const line of unfoldIcsLines(text)) {
|
|
84
|
+
if (line === 'BEGIN:VEVENT') {
|
|
85
|
+
cur = { exdates: new Set() };
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (line === 'END:VEVENT') {
|
|
89
|
+
if (cur && cur.summary && cur.startDate) {
|
|
90
|
+
events.push({ ...cur, uid: cur.uid ?? '', summary: cur.summary, startDate: cur.startDate,
|
|
91
|
+
exdates: cur.exdates });
|
|
92
|
+
}
|
|
93
|
+
cur = null;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (!cur)
|
|
97
|
+
continue;
|
|
98
|
+
const colon = line.indexOf(':');
|
|
99
|
+
if (colon < 0)
|
|
100
|
+
continue;
|
|
101
|
+
const lhs = line.slice(0, colon);
|
|
102
|
+
const value = line.slice(colon + 1);
|
|
103
|
+
const name = lhs.split(';')[0].toUpperCase();
|
|
104
|
+
if (name === 'SUMMARY')
|
|
105
|
+
cur.summary = unescapeIcsText(value.trim());
|
|
106
|
+
else if (name === 'UID')
|
|
107
|
+
cur.uid = value.trim();
|
|
108
|
+
else if (name === 'DTSTART') {
|
|
109
|
+
const t = parseIcsInstant(value.trim());
|
|
110
|
+
if (t) {
|
|
111
|
+
cur.startDate = t.date;
|
|
112
|
+
if (t.hm !== undefined)
|
|
113
|
+
cur.startHm = t.hm;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else if (name === 'DTEND') {
|
|
117
|
+
const t = parseIcsInstant(value.trim());
|
|
118
|
+
if (t) {
|
|
119
|
+
cur.endDate = t.date;
|
|
120
|
+
if (t.hm !== undefined)
|
|
121
|
+
cur.endHm = t.hm;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else if (name === 'RRULE') {
|
|
125
|
+
cur.rrule = new Map(value.split(';').map((kv) => {
|
|
126
|
+
const eq = kv.indexOf('=');
|
|
127
|
+
return [kv.slice(0, eq).toUpperCase(), kv.slice(eq + 1)];
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
else if (name === 'EXDATE') {
|
|
131
|
+
for (const v of value.split(',')) {
|
|
132
|
+
const t = parseIcsInstant(v.trim());
|
|
133
|
+
if (t)
|
|
134
|
+
cur.exdates.add(t.date);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (name === 'RECURRENCE-ID') {
|
|
138
|
+
const t = parseIcsInstant(value.trim());
|
|
139
|
+
if (t)
|
|
140
|
+
cur.recurrenceId = t.date;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return events;
|
|
144
|
+
}
|
|
145
|
+
// ── Recurrence: does this event occur on `day`? ──
|
|
146
|
+
const WEEKDAY_CODES = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
|
|
147
|
+
const dayFromKey = (key) => new Date(Number(key.slice(0, 4)), Number(key.slice(4, 6)) - 1, Number(key.slice(6, 8)));
|
|
148
|
+
const daysBetween = (a, b) => Math.round((b.getTime() - a.getTime()) / 86_400_000);
|
|
149
|
+
/** Occurrence check by bounded day-walk from DTSTART — one predicate per
|
|
150
|
+
* FREQ, counting matches so COUNT/UNTIL terminate exactly. */
|
|
151
|
+
export function occursOn(ev, dayKey) {
|
|
152
|
+
if (!ev.rrule)
|
|
153
|
+
return ev.startDate === dayKey;
|
|
154
|
+
if (ev.exdates.has(dayKey))
|
|
155
|
+
return false;
|
|
156
|
+
const freq = ev.rrule.get('FREQ') ?? '';
|
|
157
|
+
const interval = Math.max(1, Number(ev.rrule.get('INTERVAL') ?? '1') || 1);
|
|
158
|
+
const count = Number(ev.rrule.get('COUNT') ?? '0') || 0;
|
|
159
|
+
const untilRaw = ev.rrule.get('UNTIL');
|
|
160
|
+
const until = untilRaw ? parseIcsInstant(untilRaw)?.date : undefined;
|
|
161
|
+
if (until && dayKey > until)
|
|
162
|
+
return false;
|
|
163
|
+
if (dayKey < ev.startDate)
|
|
164
|
+
return false;
|
|
165
|
+
const start = dayFromKey(ev.startDate);
|
|
166
|
+
const target = dayFromKey(dayKey);
|
|
167
|
+
const span = daysBetween(start, target);
|
|
168
|
+
if (span < 0 || span > MAX_RECURRENCE_WALK_DAYS)
|
|
169
|
+
return false;
|
|
170
|
+
const byday = (ev.rrule.get('BYDAY') ?? '').split(',').filter(Boolean)
|
|
171
|
+
.map((d) => d.replace(/^[+-]?\d+/, '')); // ordinal BYDAY (1MO) → plain weekday
|
|
172
|
+
const bymonthday = Number(ev.rrule.get('BYMONTHDAY') ?? '0') || start.getDate();
|
|
173
|
+
const matches = (d, daysFromStart) => {
|
|
174
|
+
switch (freq) {
|
|
175
|
+
case 'DAILY':
|
|
176
|
+
return daysFromStart % interval === 0;
|
|
177
|
+
case 'WEEKLY': {
|
|
178
|
+
const wd = WEEKDAY_CODES[d.getDay()];
|
|
179
|
+
const inSet = byday.length > 0 ? byday.includes(wd) : d.getDay() === start.getDay();
|
|
180
|
+
// Interval counts weeks from DTSTART's week (weeks begin on Monday).
|
|
181
|
+
const mondayOffset = (dd) => (dd.getDay() + 6) % 7;
|
|
182
|
+
const weeks = Math.floor((daysFromStart + mondayOffset(start)) / 7);
|
|
183
|
+
return inSet && weeks % interval === 0;
|
|
184
|
+
}
|
|
185
|
+
case 'MONTHLY': {
|
|
186
|
+
const months = (d.getFullYear() - start.getFullYear()) * 12 + (d.getMonth() - start.getMonth());
|
|
187
|
+
return d.getDate() === bymonthday && months % interval === 0;
|
|
188
|
+
}
|
|
189
|
+
case 'YEARLY':
|
|
190
|
+
return d.getMonth() === start.getMonth() && d.getDate() === start.getDate()
|
|
191
|
+
&& (d.getFullYear() - start.getFullYear()) % interval === 0;
|
|
192
|
+
default:
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
if (!matches(target, span))
|
|
197
|
+
return false;
|
|
198
|
+
if (count > 0) {
|
|
199
|
+
// The target only counts if it is within the first COUNT occurrences.
|
|
200
|
+
let seen = 0;
|
|
201
|
+
for (let i = 0; i <= span; i++) {
|
|
202
|
+
const d = new Date(start.getFullYear(), start.getMonth(), start.getDate() + i);
|
|
203
|
+
if (matches(d, i)) {
|
|
204
|
+
seen++;
|
|
205
|
+
if (seen > count)
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
// ── Today's glance events ──
|
|
213
|
+
/** Expand all feeds' events into today's remaining schedule: all-day first,
|
|
214
|
+
* then by start time; events already over are dropped; recurrence overrides
|
|
215
|
+
* (RECURRENCE-ID) replace their master instance. */
|
|
216
|
+
export function buildTodayEvents(events, now) {
|
|
217
|
+
const today = dateKey(now);
|
|
218
|
+
const nowHm = hmKey(now);
|
|
219
|
+
const overridden = new Set(events.filter((e) => e.recurrenceId).map((e) => `${e.uid}@${e.recurrenceId}`));
|
|
220
|
+
const picked = [];
|
|
221
|
+
for (const e of events) {
|
|
222
|
+
let onToday;
|
|
223
|
+
if (e.recurrenceId) {
|
|
224
|
+
onToday = e.startDate === today; // override instance: literal date only
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
onToday = occursOn(e, today) && !(e.uid && overridden.has(`${e.uid}@${today}`));
|
|
228
|
+
// Multi-day timed event started earlier and still running → show as all-day.
|
|
229
|
+
if (!onToday && !e.rrule && e.startDate < today && (e.endDate ?? e.startDate) >= today) {
|
|
230
|
+
picked.push({ allDay: true, startHm: '', ev: { title: trimTitle(e.summary) } });
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (!onToday)
|
|
235
|
+
continue;
|
|
236
|
+
const allDay = e.startHm === undefined;
|
|
237
|
+
if (!allDay) {
|
|
238
|
+
const endHm = e.endHm && e.startDate === (e.endDate ?? e.startDate) ? e.endHm : undefined;
|
|
239
|
+
// Drop events that already ended (what's LEFT of today).
|
|
240
|
+
if ((endHm ?? e.startHm) < nowHm)
|
|
241
|
+
continue;
|
|
242
|
+
const ev = { startHm: e.startHm, title: trimTitle(e.summary) };
|
|
243
|
+
if (endHm)
|
|
244
|
+
ev.endHm = endHm;
|
|
245
|
+
picked.push({ allDay: false, startHm: e.startHm, ev });
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// DTEND of an all-day event is exclusive; a single-day event ends tomorrow.
|
|
249
|
+
picked.push({ allDay: true, startHm: '', ev: { title: trimTitle(e.summary) } });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
picked.sort((a, b) => a.allDay !== b.allDay ? (a.allDay ? -1 : 1) : a.startHm.localeCompare(b.startHm));
|
|
253
|
+
// Dedup (same title + time can arrive from two feeds).
|
|
254
|
+
const seen = new Set();
|
|
255
|
+
const out = [];
|
|
256
|
+
for (const p of picked) {
|
|
257
|
+
const key = `${p.ev.startHm ?? ''}|${p.ev.title}`;
|
|
258
|
+
if (seen.has(key))
|
|
259
|
+
continue;
|
|
260
|
+
seen.add(key);
|
|
261
|
+
out.push(p.ev);
|
|
262
|
+
if (out.length >= GLANCE_MAX_EVENTS)
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
return out;
|
|
266
|
+
}
|
|
267
|
+
const trimTitle = (s) => trimUtf8Bytes(s, GLANCE_EVENT_TITLE_MAX_BYTES);
|
|
268
|
+
export class CalendarProvider {
|
|
269
|
+
fetchImpl;
|
|
270
|
+
log;
|
|
271
|
+
cache = null;
|
|
272
|
+
inflight = null;
|
|
273
|
+
constructor(fetchImpl = fetch, log = () => { }) {
|
|
274
|
+
this.fetchImpl = fetchImpl;
|
|
275
|
+
this.log = log;
|
|
276
|
+
}
|
|
277
|
+
/** Today's remaining glance events for `cfg`, from cache when fresh.
|
|
278
|
+
* Resolves `undefined` when unconfigured or when no parse (fresh or
|
|
279
|
+
* stale-servable) exists — the glance simply omits the schedule. Today's
|
|
280
|
+
* filter always runs against the CURRENT clock, so a cached parse still
|
|
281
|
+
* drops events as they pass. Never throws. */
|
|
282
|
+
async get(cfg, now = Date.now()) {
|
|
283
|
+
if (!cfg)
|
|
284
|
+
return undefined;
|
|
285
|
+
const key = cfg.urls.join('\n');
|
|
286
|
+
const cached = this.cache;
|
|
287
|
+
if (cached && cached.key === key && now - cached.at < CALENDAR_CACHE_MS) {
|
|
288
|
+
return buildTodayEvents(cached.events, new Date(now));
|
|
289
|
+
}
|
|
290
|
+
if (this.inflight) {
|
|
291
|
+
const ev = await this.inflight;
|
|
292
|
+
return ev ? buildTodayEvents(ev, new Date(now)) : undefined;
|
|
293
|
+
}
|
|
294
|
+
this.inflight = this.fetchFresh(cfg, key, now).finally(() => { this.inflight = null; });
|
|
295
|
+
const ev = await this.inflight;
|
|
296
|
+
return ev ? buildTodayEvents(ev, new Date(now)) : undefined;
|
|
297
|
+
}
|
|
298
|
+
async fetchFresh(cfg, key, now) {
|
|
299
|
+
const ctl = new AbortController();
|
|
300
|
+
const timer = setTimeout(() => ctl.abort(), CALENDAR_FETCH_TIMEOUT_MS);
|
|
301
|
+
try {
|
|
302
|
+
const all = [];
|
|
303
|
+
for (const url of cfg.urls) {
|
|
304
|
+
const res = await this.fetchImpl(url, { signal: ctl.signal });
|
|
305
|
+
if (!res.ok)
|
|
306
|
+
throw new Error(`ics HTTP ${res.status}`);
|
|
307
|
+
all.push(...parseIcsEvents(await res.text()));
|
|
308
|
+
}
|
|
309
|
+
this.cache = { key, at: now, events: all };
|
|
310
|
+
return all;
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
this.log(`[calendar] fetch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
314
|
+
const cached = this.cache;
|
|
315
|
+
if (cached && cached.key === key && now - cached.at < CALENDAR_STALE_SERVE_MS)
|
|
316
|
+
return cached.events;
|
|
317
|
+
return undefined;
|
|
318
|
+
}
|
|
319
|
+
finally {
|
|
320
|
+
clearTimeout(timer);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=calendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar.js","sourceRoot":"","sources":["../src/calendar.ts"],"names":[],"mappings":"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"}
|
package/dist/card-feed.d.ts
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* HTTP routes live in daemon-server.ts. Contract: shared/src/protocol.ts
|
|
5
5
|
* § Card Feed Pull Sync + docs/esp32-client-contract.md § Pull sync.
|
|
6
6
|
*
|
|
7
|
-
* M6 derives
|
|
8
|
-
* broadcasts). M7 generalizes to daemon card modules
|
|
9
|
-
*
|
|
7
|
+
* M6 derives cards from live sessions (the same rows `sessions_list`
|
|
8
|
+
* broadcasts). M7 generalizes to daemon card modules; the Node daemon injects
|
|
9
|
+
* Autonomous Pocket's PULSE / NUDGE / QUEST producers into this pure builder.
|
|
10
10
|
*/
|
|
11
|
-
import type { SessionInfo, FeedCard, CardFeedResponse, OutboxPushRequest, OutboxPushResponse } from '@agentdeck/shared';
|
|
11
|
+
import type { SessionInfo, FeedCard, CardFeedResponse, CardFeedGlance, GlanceEvent, GlanceUsageRow, GlanceWeather, OutboxPushRequest, OutboxPushResponse } from '@agentdeck/shared';
|
|
12
|
+
import type { UsageEvent } from './types.js';
|
|
12
13
|
import { type CardModule } from './card-modules.js';
|
|
13
14
|
/** A pulled permission gate is answerable only while the PreToolUse long-poll
|
|
14
15
|
* still holds the hook open (~60s) — pulled copies are honest about that. */
|
|
@@ -20,7 +21,40 @@ export declare const AWAITING_PROMPT_TTL_MS: number;
|
|
|
20
21
|
* interactive prompts are `live` (grey out offline, TTL-expire); everything
|
|
21
22
|
* else is a read-only `info` row. */
|
|
22
23
|
export declare function classifySessionCard(s: SessionInfo, now: number): Pick<FeedCard, 'actionClass' | 'expiresAt'>;
|
|
23
|
-
|
|
24
|
+
/** UTF-8 byte-budget trim on a rune boundary — the device caps are bytes,
|
|
25
|
+
* never code points (CJK is 3 bytes/char). */
|
|
26
|
+
export declare function trimUtf8Bytes(s: string, maxBytes: number): string;
|
|
27
|
+
/** Provider quota rows from the daemon's aggregate usage event. Claude first
|
|
28
|
+
* (the primary subscription on this product), then Codex. A provider with no
|
|
29
|
+
* numbers at all gets no row — the glance never renders an empty gauge. */
|
|
30
|
+
export declare function buildGlanceUsage(usage: UsageEvent | undefined): GlanceUsageRow[];
|
|
31
|
+
/** Work wrap-up lines — "what was being worked on", one line per session,
|
|
32
|
+
* attention first. Pre-trimmed to the device byte budget; the renderer only
|
|
33
|
+
* draws. */
|
|
34
|
+
export declare function buildGlanceWrapup(sessions: SessionInfo[]): string[];
|
|
35
|
+
export declare function buildGlance(input: {
|
|
36
|
+
sessions: SessionInfo[];
|
|
37
|
+
usage?: UsageEvent;
|
|
38
|
+
weather?: GlanceWeather;
|
|
39
|
+
events?: GlanceEvent[];
|
|
40
|
+
}): CardFeedGlance | undefined;
|
|
41
|
+
/** FNV-1a 32-bit over the canonical feed content: cards with volatile fields
|
|
42
|
+
* stripped (see `VOLATILE_SESSION_FIELDS`) plus the glance verbatim. Matching
|
|
43
|
+
* sigs mean the device's cached deck is still exactly what the daemon would
|
|
44
|
+
* send. */
|
|
45
|
+
export declare function computeDeckSig(cards: FeedCard[], glance?: CardFeedGlance): string;
|
|
46
|
+
export interface BuildCardFeedOpts {
|
|
47
|
+
/** Sleep-dashboard summary to embed (and cover with the signature). */
|
|
48
|
+
glance?: CardFeedGlance;
|
|
49
|
+
/** `?sig=` echo from the device — when it matches the current signature the
|
|
50
|
+
* response short-circuits to `unchanged: true` with empty cards. */
|
|
51
|
+
echoSig?: string;
|
|
52
|
+
/** Pocket-reader clients consume daemon-authored module cards, not live
|
|
53
|
+
* session projections. Omitting those rows keeps the portable feed small
|
|
54
|
+
* and makes AgentDeck one content source rather than the product shell. */
|
|
55
|
+
includeSessions?: boolean;
|
|
56
|
+
}
|
|
57
|
+
export declare function buildCardFeed(sessions: SessionInfo[], now?: number, modules?: CardModule[], opts?: BuildCardFeedOpts): CardFeedResponse;
|
|
24
58
|
export interface OutboxApplyDeps {
|
|
25
59
|
/** Current enriched roster — validity checks run against *live* state. */
|
|
26
60
|
sessions: SessionInfo[];
|
|
@@ -56,6 +90,13 @@ export interface FeedPullEvent {
|
|
|
56
90
|
driftPct?: number;
|
|
57
91
|
/** Gap within `PULL_CADENCE_TOLERANCE` of the advertised cadence. */
|
|
58
92
|
cadenceHonoured?: boolean;
|
|
93
|
+
/** Conditional pull answered `unchanged` — the deck signature matched. */
|
|
94
|
+
unchanged?: boolean;
|
|
95
|
+
/** Device telemetry from the `GET /feed` query string (`batt`/`mv`/`rssi`) —
|
|
96
|
+
* the only battery/link observability a wake-sync-sleep device has. */
|
|
97
|
+
battPct?: number;
|
|
98
|
+
battMv?: number;
|
|
99
|
+
rssiDbm?: number;
|
|
59
100
|
}
|
|
60
101
|
export interface FeedPullClient {
|
|
61
102
|
client: string;
|
|
@@ -70,9 +111,24 @@ export interface FeedPullClient {
|
|
|
70
111
|
medianIntervalSec?: number;
|
|
71
112
|
/** Intervals that landed inside the tolerance band, out of `pulls - 1`. */
|
|
72
113
|
cadenceHonouredCount: number;
|
|
114
|
+
/** Latest reported telemetry (absent until the device sends it). */
|
|
115
|
+
lastBattPct?: number;
|
|
116
|
+
lastBattMv?: number;
|
|
117
|
+
lastRssiDbm?: number;
|
|
118
|
+
/** Pulls answered `unchanged` — how often the conditional pull saved work. */
|
|
119
|
+
unchangedCount: number;
|
|
73
120
|
}
|
|
74
121
|
/** `::ffff:192.168.68.77` and `::1` are the same peers as their v4 forms. */
|
|
75
122
|
export declare function normalizeClientIp(ip: string): string;
|
|
123
|
+
/** Telemetry that rides the `GET /feed` query string. */
|
|
124
|
+
export interface PullTelemetry {
|
|
125
|
+
battPct?: number;
|
|
126
|
+
battMv?: number;
|
|
127
|
+
rssiDbm?: number;
|
|
128
|
+
}
|
|
129
|
+
/** Parse `batt`/`mv`/`rssi` query params, dropping anything non-numeric or
|
|
130
|
+
* out of physical range — telemetry is advisory, never trusted blindly. */
|
|
131
|
+
export declare function parsePullTelemetry(params: URLSearchParams): PullTelemetry;
|
|
76
132
|
/** In-memory (daemon-lifetime) record of card-feed pulls, keyed by client IP.
|
|
77
133
|
* Deliberately not persisted: it answers "is the cadence working *now*". */
|
|
78
134
|
export declare class FeedPullTracker {
|
|
@@ -92,6 +148,8 @@ export declare class FeedPullTracker {
|
|
|
92
148
|
cards: number;
|
|
93
149
|
nextPullSec: number;
|
|
94
150
|
now?: number;
|
|
151
|
+
unchanged?: boolean;
|
|
152
|
+
telemetry?: PullTelemetry;
|
|
95
153
|
}): FeedPullEvent;
|
|
96
154
|
/** Most recent pulls, newest first. */
|
|
97
155
|
recent(limit?: number): FeedPullEvent[];
|
package/dist/card-feed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card-feed.d.ts","sourceRoot":"","sources":["../src/card-feed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,gBAAgB,
|
|
1
|
+
{"version":3,"file":"card-feed.d.ts","sourceRoot":"","sources":["../src/card-feed.ts"],"names":[],"mappings":"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"}
|