@agentdeck/bridge 1.0.21 → 1.0.23
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/apme/activity-history.d.ts +59 -0
- package/dist/apme/activity-history.d.ts.map +1 -0
- package/dist/apme/activity-history.js +265 -0
- package/dist/apme/activity-history.js.map +1 -0
- package/dist/apme/dashboard-html.d.ts.map +1 -1
- package/dist/apme/dashboard-html.js +40 -6
- package/dist/apme/dashboard-html.js.map +1 -1
- package/dist/apme/http.d.ts +1 -0
- package/dist/apme/http.d.ts.map +1 -1
- package/dist/apme/http.js +9 -0
- package/dist/apme/http.js.map +1 -1
- package/dist/apme/runner.d.ts +20 -0
- package/dist/apme/runner.d.ts.map +1 -1
- package/dist/apme/runner.js +57 -0
- package/dist/apme/runner.js.map +1 -1
- package/dist/apme/settings.d.ts +21 -4
- package/dist/apme/settings.d.ts.map +1 -1
- package/dist/apme/settings.js +29 -5
- package/dist/apme/settings.js.map +1 -1
- package/dist/apme/store.d.ts +7 -0
- package/dist/apme/store.d.ts.map +1 -1
- package/dist/apme/store.js +35 -0
- package/dist/apme/store.js.map +1 -1
- package/dist/ble-sync-spawn.d.ts +27 -0
- package/dist/ble-sync-spawn.d.ts.map +1 -1
- package/dist/ble-sync-spawn.js +32 -0
- package/dist/ble-sync-spawn.js.map +1 -1
- package/dist/bridge-core.d.ts +21 -4
- package/dist/bridge-core.d.ts.map +1 -1
- package/dist/bridge-core.js +52 -23
- package/dist/bridge-core.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +261 -13
- package/dist/cli.js.map +1 -1
- package/dist/codex-rate-limits-live.d.ts +58 -9
- package/dist/codex-rate-limits-live.d.ts.map +1 -1
- package/dist/codex-rate-limits-live.js +64 -15
- package/dist/codex-rate-limits-live.js.map +1 -1
- package/dist/codex-rate-limits.d.ts +2 -2
- package/dist/codex-rate-limits.d.ts.map +1 -1
- package/dist/codex-rate-limits.js +34 -16
- package/dist/codex-rate-limits.js.map +1 -1
- package/dist/daemon-server.d.ts +46 -2
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +165 -44
- package/dist/daemon-server.js.map +1 -1
- package/dist/daemon-takeover.d.ts +3 -0
- package/dist/daemon-takeover.d.ts.map +1 -1
- package/dist/daemon-takeover.js +5 -0
- package/dist/daemon-takeover.js.map +1 -1
- package/dist/daemon.js +1 -1
- package/dist/esp32-flash-lease.d.ts +47 -0
- package/dist/esp32-flash-lease.d.ts.map +1 -0
- package/dist/esp32-flash-lease.js +84 -0
- package/dist/esp32-flash-lease.js.map +1 -0
- package/dist/esp32-flash-transport.d.ts +90 -0
- package/dist/esp32-flash-transport.d.ts.map +1 -0
- package/dist/esp32-flash-transport.js +157 -0
- package/dist/esp32-flash-transport.js.map +1 -0
- package/dist/esp32-flash.d.ts +171 -0
- package/dist/esp32-flash.d.ts.map +1 -0
- package/dist/esp32-flash.js +523 -0
- package/dist/esp32-flash.js.map +1 -0
- package/dist/esp32-serial.d.ts +9 -1
- package/dist/esp32-serial.d.ts.map +1 -1
- package/dist/esp32-serial.js +74 -1
- package/dist/esp32-serial.js.map +1 -1
- package/dist/esptool-js-node.d.ts +17 -0
- package/dist/esptool-js-node.d.ts.map +1 -0
- package/dist/esptool-js-node.js +17 -0
- package/dist/esptool-js-node.js.map +1 -0
- package/dist/hook-server.d.ts.map +1 -1
- package/dist/hook-server.js +17 -0
- package/dist/hook-server.js.map +1 -1
- package/dist/idotmatrix/idotmatrix-daemon-sync.d.ts.map +1 -1
- package/dist/idotmatrix/idotmatrix-daemon-sync.js +13 -1
- package/dist/idotmatrix/idotmatrix-daemon-sync.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.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 +101 -7
- package/dist/python-ble-runtime.js.map +1 -1
- package/dist/review-runner.d.ts.map +1 -1
- package/dist/review-runner.js +27 -9
- package/dist/review-runner.js.map +1 -1
- package/dist/timebox/timebox-daemon-sync.d.ts.map +1 -1
- package/dist/timebox/timebox-daemon-sync.js +11 -1
- package/dist/timebox/timebox-daemon-sync.js.map +1 -1
- package/dist/timeline-summarizer.d.ts +7 -2
- package/dist/timeline-summarizer.d.ts.map +1 -1
- package/dist/timeline-summarizer.js +13 -69
- package/dist/timeline-summarizer.js.map +1 -1
- package/dist/usage-api.d.ts +28 -1
- package/dist/usage-api.d.ts.map +1 -1
- package/dist/usage-api.js +74 -33
- package/dist/usage-api.js.map +1 -1
- package/dist/usage-event.d.ts.map +1 -1
- package/dist/usage-event.js +2 -17
- package/dist/usage-event.js.map +1 -1
- package/package.json +6 -4
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentdeck esp32 flash <board>` — the reliable half of the firmware install
|
|
3
|
+
* story. (The browser flasher at /flash/ is the reachable half.)
|
|
4
|
+
*
|
|
5
|
+
* WHAT IT WRITES. One `agentdeck-<board>-merged.bin` at offset 0x0, on every
|
|
6
|
+
* chip. `esptool merge-bin --target-offset 0x0` has already put each board's
|
|
7
|
+
* bootloader where its ROM looks for it — classic ESP32 at 0x1000 inside the
|
|
8
|
+
* image, P4 at 0x2000, S3/C6 at 0x0 — so nothing downstream branches on chip
|
|
9
|
+
* family. The old release notes told users to write the app alone at 0x10000,
|
|
10
|
+
* which cannot bring a board up: `boot_app0.bin` was never published, so a
|
|
11
|
+
* stale otadata boots the previous slot.
|
|
12
|
+
*
|
|
13
|
+
* WHAT IT WILL NOT WRITE. The preflight in `@agentdeck/shared` is shared
|
|
14
|
+
* verbatim with the browser, and there is no `--force`. Writing an S3 image to
|
|
15
|
+
* a classic ESP32, or a 16MB-header image to an 8MB part, is how these boards
|
|
16
|
+
* get bricked — and the recovery tool for a bricked board is this one.
|
|
17
|
+
*/
|
|
18
|
+
import { createHash } from 'node:crypto';
|
|
19
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
import { execFile } from 'node:child_process';
|
|
22
|
+
import { promisify } from 'node:util';
|
|
23
|
+
import { ESPLoader, Transport } from './esptool-js-node.js';
|
|
24
|
+
import { ESP32_BOARD_BY_TARGET, esp32FlashIdIsUsable, esp32PreflightVerdict, } from '@agentdeck/shared';
|
|
25
|
+
import { getDataDir } from './session-registry.js';
|
|
26
|
+
import { listCandidatePorts, loadSerialPort, NodeWebSerialPort } from './esp32-flash-transport.js';
|
|
27
|
+
const execFileAsync = promisify(execFile);
|
|
28
|
+
export const GITHUB_REPO = 'puritysb/AgentDeck';
|
|
29
|
+
/* ------------------------------------------------------------ board lookup */
|
|
30
|
+
export function resolveFlashBoard(target) {
|
|
31
|
+
const board = ESP32_BOARD_BY_TARGET[target];
|
|
32
|
+
if (!board) {
|
|
33
|
+
const known = Object.keys(ESP32_BOARD_BY_TARGET).sort().join(', ');
|
|
34
|
+
throw new Error(`unknown board "${target}". Known targets: ${known}`);
|
|
35
|
+
}
|
|
36
|
+
return board;
|
|
37
|
+
}
|
|
38
|
+
const api = async (path) => {
|
|
39
|
+
const res = await fetch(`https://api.github.com${path}`, {
|
|
40
|
+
headers: { Accept: 'application/vnd.github+json', 'User-Agent': 'agentdeck-cli' },
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok)
|
|
43
|
+
throw new Error(`GitHub API ${path} → HTTP ${res.status}`);
|
|
44
|
+
return res.json();
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Every published `esp32-v*` tag, newest first.
|
|
48
|
+
*
|
|
49
|
+
* PAGED, because a single page is a silent cap. `per_page` maxes at 100 and
|
|
50
|
+
* this repo cuts ~6 tags a round across its channels, so once ~100 releases
|
|
51
|
+
* accumulate after the newest esp32 cut, one page stops containing it — and the
|
|
52
|
+
* damage is not "no answer" but a WRONG one: the existence check would report a
|
|
53
|
+
* genuinely published version as unpublished and quietly fall back to an older
|
|
54
|
+
* release. Stops at the first page that yields no esp32 tag once some are
|
|
55
|
+
* already known, so the common case is still one request.
|
|
56
|
+
*/
|
|
57
|
+
export async function listFirmwareTags(maxPages = 5) {
|
|
58
|
+
const found = [];
|
|
59
|
+
for (let page = 1; page <= maxPages; page++) {
|
|
60
|
+
const releases = (await api(`/repos/${GITHUB_REPO}/releases?per_page=100&page=${page}`));
|
|
61
|
+
if (releases.length === 0)
|
|
62
|
+
break;
|
|
63
|
+
const esp32 = releases.filter((r) => typeof r.tag_name === 'string' && r.tag_name.startsWith('esp32-v'));
|
|
64
|
+
found.push(...esp32.map((r) => ({ tag: r.tag_name, at: String(r.created_at) })));
|
|
65
|
+
// Releases come back newest-first, so once this page has none and we
|
|
66
|
+
// already have some, everything older is older still.
|
|
67
|
+
if (esp32.length === 0 && found.length > 0)
|
|
68
|
+
break;
|
|
69
|
+
if (releases.length < 100)
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
return found.sort((a, b) => (a.at < b.at ? 1 : -1)).map((r) => r.tag);
|
|
73
|
+
}
|
|
74
|
+
/** Newest `esp32-v*` tag, or undefined when the repo has none. */
|
|
75
|
+
export async function latestFirmwareTag() {
|
|
76
|
+
return (await listFirmwareTags())[0];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Which release a bare `agentdeck esp32 flash <board>` takes firmware from.
|
|
80
|
+
*
|
|
81
|
+
* TWO RULES, IN THIS ORDER, AND NEITHER WORKS ALONE. The checkout's
|
|
82
|
+
* `FIRMWARE_VERSION` names the release this source tree belongs to — but it is
|
|
83
|
+
* bumped BEFORE the tag is pushed, so during that window it names a release
|
|
84
|
+
* that does not exist yet. Taking it unconditionally is how the first command
|
|
85
|
+
* in the docs came to fail from every checkout the moment the version was
|
|
86
|
+
* bumped (and the 404 it produced was indistinguishable from "this release has
|
|
87
|
+
* no manifest", so it also misdiagnosed itself).
|
|
88
|
+
*
|
|
89
|
+
* Deliberately the same shape as `resolveTag` in
|
|
90
|
+
* `scripts/fetch-flash-firmware.mjs`. That one runs in CI with `gh`; this one
|
|
91
|
+
* runs on a user's machine with `fetch`. Same rules, same reported `source`.
|
|
92
|
+
*/
|
|
93
|
+
export function pickFirmwareTag(configVersion, published) {
|
|
94
|
+
if (configVersion) {
|
|
95
|
+
const candidate = `esp32-v${configVersion}`;
|
|
96
|
+
if (published.includes(candidate))
|
|
97
|
+
return { tag: candidate, source: 'config' };
|
|
98
|
+
}
|
|
99
|
+
const latest = published[0];
|
|
100
|
+
if (!latest)
|
|
101
|
+
throw new Error(`no esp32-v* release found in ${GITHUB_REPO}`);
|
|
102
|
+
return { tag: latest, source: 'latest' };
|
|
103
|
+
}
|
|
104
|
+
export function firmwareVersionFromCheckout(configH) {
|
|
105
|
+
const m = /FIRMWARE_VERSION\s*=\s*"([^"]+)"/.exec(configH);
|
|
106
|
+
return m?.[1];
|
|
107
|
+
}
|
|
108
|
+
export function firmwareCacheDir(tag) {
|
|
109
|
+
return join(getDataDir(), 'firmware', tag);
|
|
110
|
+
}
|
|
111
|
+
const sha256 = (buf) => createHash('sha256').update(buf).digest('hex');
|
|
112
|
+
async function downloadAsset(tag, file, dest) {
|
|
113
|
+
const url = `https://github.com/${GITHUB_REPO}/releases/download/${tag}/${file}`;
|
|
114
|
+
const res = await fetch(url, { redirect: 'follow' });
|
|
115
|
+
if (!res.ok)
|
|
116
|
+
throw new Error(`${file} → HTTP ${res.status} (${url})`);
|
|
117
|
+
const bytes = Buffer.from(await res.arrayBuffer());
|
|
118
|
+
mkdirSync(join(dest, '..'), { recursive: true });
|
|
119
|
+
const tmp = `${dest}.tmp`;
|
|
120
|
+
writeFileSync(tmp, bytes);
|
|
121
|
+
renameSync(tmp, dest);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get the merged image for a board, verifying its sha256 EVERY time — on a
|
|
125
|
+
* fresh download and on every cache hit. The cache key proves which release a
|
|
126
|
+
* file came from, never that its bits are still intact, and a bit-rotted cached
|
|
127
|
+
* image is a bricked board.
|
|
128
|
+
*/
|
|
129
|
+
export async function resolveFirmware(board, opts = {}) {
|
|
130
|
+
const log = opts.log ?? (() => { });
|
|
131
|
+
if (opts.firmwarePath) {
|
|
132
|
+
if (!existsSync(opts.firmwarePath))
|
|
133
|
+
throw new Error(`no such firmware file: ${opts.firmwarePath}`);
|
|
134
|
+
// An explicit path is the user overriding the manifest, so there is no hash
|
|
135
|
+
// to check against — say so rather than implying it was verified.
|
|
136
|
+
log(`Using ${opts.firmwarePath} (no manifest hash to check against)`);
|
|
137
|
+
return {
|
|
138
|
+
tag: 'local',
|
|
139
|
+
image: readFileSync(opts.firmwarePath),
|
|
140
|
+
source: 'file',
|
|
141
|
+
path: opts.firmwarePath,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
let tag = opts.tag;
|
|
145
|
+
const configVersion = opts.checkoutConfigH
|
|
146
|
+
? firmwareVersionFromCheckout(opts.checkoutConfigH)
|
|
147
|
+
: undefined;
|
|
148
|
+
if (!tag && opts.offline) {
|
|
149
|
+
// Offline cannot ask which releases exist, so it cannot apply rule 2's
|
|
150
|
+
// existence check. The checkout's own version is a LOCAL fact though, and
|
|
151
|
+
// using it is the whole point of an offline run against a warm cache — so
|
|
152
|
+
// take it optimistically here and let the cache lookup below produce the
|
|
153
|
+
// error if nothing was cached for it.
|
|
154
|
+
if (!configVersion)
|
|
155
|
+
throw new Error('--offline needs --tag or --firmware; nothing to resolve');
|
|
156
|
+
tag = `esp32-v${configVersion}`;
|
|
157
|
+
}
|
|
158
|
+
if (!tag) {
|
|
159
|
+
// One API call answers both rules: is the checkout's version published, and
|
|
160
|
+
// what is the newest release. Checking existence is the whole point — see
|
|
161
|
+
// pickFirmwareTag.
|
|
162
|
+
const picked = pickFirmwareTag(configVersion, await listFirmwareTags());
|
|
163
|
+
tag = picked.tag;
|
|
164
|
+
log(`Firmware release: ${tag} (${picked.source === 'config'
|
|
165
|
+
? "this checkout's esp32/src/config.h"
|
|
166
|
+
: 'newest published esp32-v* release'})`);
|
|
167
|
+
}
|
|
168
|
+
const dir = firmwareCacheDir(tag);
|
|
169
|
+
const manifestPath = join(dir, 'manifest.json');
|
|
170
|
+
if (!existsSync(manifestPath)) {
|
|
171
|
+
if (opts.offline)
|
|
172
|
+
throw new Error(`--offline: no cached manifest for ${tag} at ${manifestPath}`);
|
|
173
|
+
log(`Fetching manifest for ${tag}…`);
|
|
174
|
+
try {
|
|
175
|
+
await downloadAsset(tag, 'manifest.json', manifestPath);
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
// A 404 here is not a network fault — every esp32-v* up to 1.0.6 predates
|
|
179
|
+
// the merged-image pipeline and publishes no manifest at all. Saying so
|
|
180
|
+
// points at the fix; "HTTP 404" points at nothing.
|
|
181
|
+
if (/HTTP 404/.test(String(e))) {
|
|
182
|
+
// Reached only after the tag was confirmed to exist (pickFirmwareTag
|
|
183
|
+
// checks the published list), so this is specifically "that release has
|
|
184
|
+
// no manifest", never "no such release" — the two produce identical
|
|
185
|
+
// 404s and conflating them misdiagnoses both.
|
|
186
|
+
throw new Error(`${tag} publishes no manifest.json — it predates the merged-image pipeline.\n` +
|
|
187
|
+
' Every release up to esp32-v1.0.6 is in that state. Either cut a newer\n' +
|
|
188
|
+
' esp32-v* release, pass --tag once one exists, or pass --firmware with a\n' +
|
|
189
|
+
' locally built image.');
|
|
190
|
+
}
|
|
191
|
+
throw e;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
195
|
+
const entry = manifest.boards.find((b) => b.id === board.id);
|
|
196
|
+
if (!entry?.merged) {
|
|
197
|
+
throw new Error(`${tag} publishes no merged image for ${board.id}. ` +
|
|
198
|
+
'Releases before the merged-image pipeline have none — use a newer --tag, or --firmware.');
|
|
199
|
+
}
|
|
200
|
+
const imagePath = join(dir, entry.merged.file);
|
|
201
|
+
let source = 'cache';
|
|
202
|
+
if (!existsSync(imagePath) || sha256(readFileSync(imagePath)) !== entry.merged.sha256) {
|
|
203
|
+
if (opts.offline)
|
|
204
|
+
throw new Error(`--offline: ${entry.merged.file} is not cached (or failed its hash)`);
|
|
205
|
+
log(`Downloading ${entry.merged.file} (${(entry.merged.size / 1e6).toFixed(1)} MB)…`);
|
|
206
|
+
await downloadAsset(tag, entry.merged.file, imagePath);
|
|
207
|
+
source = 'download';
|
|
208
|
+
}
|
|
209
|
+
const image = readFileSync(imagePath);
|
|
210
|
+
const got = sha256(image);
|
|
211
|
+
if (got !== entry.merged.sha256) {
|
|
212
|
+
throw new Error(`${entry.merged.file}: sha256 ${got} ≠ manifest ${entry.merged.sha256}. Refusing to write unverified bits.`);
|
|
213
|
+
}
|
|
214
|
+
if (image.length !== entry.merged.size) {
|
|
215
|
+
throw new Error(`${entry.merged.file}: ${image.length} bytes, manifest says ${entry.merged.size}`);
|
|
216
|
+
}
|
|
217
|
+
return { tag, image, entry, source, path: imagePath };
|
|
218
|
+
}
|
|
219
|
+
export function parseLsofHolders(stdout) {
|
|
220
|
+
const holders = [];
|
|
221
|
+
let pid = 0;
|
|
222
|
+
// `-F cp` still emits `f<fd>` lines; anything that is not p/c is ignored.
|
|
223
|
+
for (const line of stdout.split('\n')) {
|
|
224
|
+
if (line.startsWith('p'))
|
|
225
|
+
pid = Number(line.slice(1));
|
|
226
|
+
else if (line.startsWith('c'))
|
|
227
|
+
holders.push({ command: line.slice(1), pid });
|
|
228
|
+
}
|
|
229
|
+
return holders;
|
|
230
|
+
}
|
|
231
|
+
export async function scanPortHolders(port) {
|
|
232
|
+
if (process.platform === 'win32') {
|
|
233
|
+
// No lsof at all. Stated as unknown rather than free: on Windows the open()
|
|
234
|
+
// failure is the only signal, and pretending otherwise would be a claim.
|
|
235
|
+
return { known: false, reason: 'lsof is not available on Windows' };
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
const { stdout } = await execFileAsync('lsof', ['-F', 'cp', port], { timeout: 5000 });
|
|
239
|
+
return { known: true, holders: parseLsofHolders(stdout) };
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
const err = e;
|
|
243
|
+
// The ONE failure that means "free": lsof ran, found nothing, exited 1 with
|
|
244
|
+
// no output. Everything else is a failure to observe.
|
|
245
|
+
if (err.code === 1 && !err.killed && !String(err.stdout ?? '').trim()) {
|
|
246
|
+
return { known: true, holders: [] };
|
|
247
|
+
}
|
|
248
|
+
if (err.killed)
|
|
249
|
+
return { known: false, reason: 'lsof timed out after 5s' };
|
|
250
|
+
if (err.code === 'ENOENT')
|
|
251
|
+
return { known: false, reason: 'lsof is not installed' };
|
|
252
|
+
return { known: false, reason: `lsof failed (${String(err.code ?? 'unknown error')})` };
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/** Back-compat convenience: holders, or none when they could not be observed. */
|
|
256
|
+
export async function whoHoldsPort(port) {
|
|
257
|
+
const scan = await scanPortHolders(port);
|
|
258
|
+
return scan.known ? scan.holders : [];
|
|
259
|
+
}
|
|
260
|
+
/** Processes AgentDeck itself is responsible for, and can therefore ask to let go. */
|
|
261
|
+
const OURS = /^(node|agentdeck|AgentDeck)$/;
|
|
262
|
+
export function classifyHolders(holders) {
|
|
263
|
+
return {
|
|
264
|
+
ours: holders.filter((h) => OURS.test(h.command)),
|
|
265
|
+
foreign: holders.filter((h) => !OURS.test(h.command)),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Bound a teardown await that can never be trusted to return.
|
|
270
|
+
*
|
|
271
|
+
* `Transport.disconnect()` calls `waitForUnlock()`, a `while (locked)` spin
|
|
272
|
+
* with NO deadline — and `Transport.write()` has no try/finally, so a rejected
|
|
273
|
+
* `writer.write()` (board unplugged, native-USB CDC re-enumerating, driver
|
|
274
|
+
* error mid-write) leaves the writable stream locked permanently. The spin then
|
|
275
|
+
* never exits.
|
|
276
|
+
*
|
|
277
|
+
* That matters far more than a leaked handle: this runs in the `finally` that
|
|
278
|
+
* the CLI's own `finally` waits on before POSTing `/esp32/serial/resume`. A
|
|
279
|
+
* hang there means the command produces no further output AND the daemon's
|
|
280
|
+
* serial layer stays down for the entire 420s/900s lease. Abandoning the
|
|
281
|
+
* teardown is strictly better than inheriting its hang — the fd is released
|
|
282
|
+
* when the process exits, and the lease expires on its own clock.
|
|
283
|
+
*
|
|
284
|
+
* Repo rule: every await on an external peer gets a bound.
|
|
285
|
+
*/
|
|
286
|
+
async function bounded(work, ms, what) {
|
|
287
|
+
let timer;
|
|
288
|
+
try {
|
|
289
|
+
await Promise.race([
|
|
290
|
+
work.catch(() => undefined),
|
|
291
|
+
new Promise((resolve) => { timer = setTimeout(resolve, ms); }),
|
|
292
|
+
]);
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
// A teardown failure is never worth surfacing over the outcome it follows.
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
if (timer)
|
|
299
|
+
clearTimeout(timer);
|
|
300
|
+
}
|
|
301
|
+
void what;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Connect, identify, refuse-or-write, verify by MD5. Mirrors the browser's
|
|
305
|
+
* `flash.ts` step for step; the two share `esp32PreflightVerdict` so they can
|
|
306
|
+
* never disagree about which board may be written.
|
|
307
|
+
*/
|
|
308
|
+
export async function flashBoard(board, portPath, image, geometry, opts = {}, cb = {}) {
|
|
309
|
+
const SerialPort = await loadSerialPort();
|
|
310
|
+
if (!SerialPort) {
|
|
311
|
+
throw new Error('serialport is not installed (it is an optional native dependency).\n' +
|
|
312
|
+
' Install it with: npm install -g serialport\n' +
|
|
313
|
+
' or reinstall AgentDeck so the optional dependency builds: npx @agentdeck/setup\n' +
|
|
314
|
+
' Alternatively flash from a browser at https://puritysb.github.io/AgentDeck/flash/');
|
|
315
|
+
}
|
|
316
|
+
const info = (await listCandidatePorts()).find((p) => p.path === portPath);
|
|
317
|
+
const device = new NodeWebSerialPort(portPath, {
|
|
318
|
+
usbVendorId: info?.usbVendorId,
|
|
319
|
+
usbProductId: info?.usbProductId,
|
|
320
|
+
});
|
|
321
|
+
const t0 = Date.now();
|
|
322
|
+
const transport = new Transport(device, false);
|
|
323
|
+
const loader = new ESPLoader({
|
|
324
|
+
transport,
|
|
325
|
+
baudrate: opts.baud ?? board.uploadBaud,
|
|
326
|
+
terminal: {
|
|
327
|
+
clean() { },
|
|
328
|
+
writeLine: (d) => cb.log?.(d),
|
|
329
|
+
write: (d) => cb.log?.(d),
|
|
330
|
+
},
|
|
331
|
+
debugLogging: false,
|
|
332
|
+
});
|
|
333
|
+
try {
|
|
334
|
+
cb.onPhase?.('connect');
|
|
335
|
+
let chip;
|
|
336
|
+
if (board.stub) {
|
|
337
|
+
chip = await loader.main(board.before);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
// The no-stub equivalent of main(): everything except runStub(). Some
|
|
341
|
+
// envs pin --no-stub and some REQUIRE the stub (t_display_pro's
|
|
342
|
+
// "stub + 230400" is a verified combination; t_embed broke when the
|
|
343
|
+
// CH340 envs' no-stub flags were copied onto it) — that axis is in the
|
|
344
|
+
// SSOT, not decided here.
|
|
345
|
+
await loader.detectChip(board.before);
|
|
346
|
+
chip = await loader.chip.getChipDescription(loader);
|
|
347
|
+
if (loader.chip.postConnect)
|
|
348
|
+
await loader.chip.postConnect(loader);
|
|
349
|
+
if ((opts.baud ?? board.uploadBaud) !== 115200)
|
|
350
|
+
await loader.changeBaud();
|
|
351
|
+
}
|
|
352
|
+
cb.onPhase?.('identify');
|
|
353
|
+
const mac = await loader.chip.readMac(loader);
|
|
354
|
+
const flashId = (await loader.readFlashId()).toString(16);
|
|
355
|
+
// detectFlashSize() answers "4MB" when it cannot decode the id, so an
|
|
356
|
+
// unusable id must stay unknown rather than becoming a confident wrong
|
|
357
|
+
// number that then gates the write.
|
|
358
|
+
const flashSize = esp32FlashIdIsUsable(flashId) ? await loader.detectFlashSize() : undefined;
|
|
359
|
+
const verdict = esp32PreflightVerdict({
|
|
360
|
+
board,
|
|
361
|
+
surface: 'cli',
|
|
362
|
+
detectedChip: chip,
|
|
363
|
+
detectedFlashSize: flashSize,
|
|
364
|
+
// Only when the geometry came from a manifest. A hand-supplied
|
|
365
|
+
// --firmware has none to disagree with, and inventing one from the board
|
|
366
|
+
// spec would make the check compare a value against itself.
|
|
367
|
+
imageGeometry: opts.imageIsFromManifest
|
|
368
|
+
? { chipFamily: String(geometry.chipFamily), flashSize: geometry.flashSize }
|
|
369
|
+
: undefined,
|
|
370
|
+
});
|
|
371
|
+
if (!verdict.mayWrite) {
|
|
372
|
+
throw new Error(`refusing to write ${board.id}: ${verdict.code}\n` +
|
|
373
|
+
` detected: ${chip}${flashSize ? `, flash ${flashSize}` : ''}\n` +
|
|
374
|
+
` expected: ${board.chipFamily}, flash ${board.flashSize}\n` +
|
|
375
|
+
(verdict.code === 'image-geometry-mismatch'
|
|
376
|
+
? ` the image says: ${geometry.chipFamily ?? '?'}, flash ${geometry.flashSize}\n` +
|
|
377
|
+
' The release you are installing was built for different geometry than this\n' +
|
|
378
|
+
' build knows this board to have. Use a matching --tag.\n'
|
|
379
|
+
: '') +
|
|
380
|
+
' There is no --force. Pick the board you actually have.');
|
|
381
|
+
}
|
|
382
|
+
if (opts.eraseAll && !board.stub) {
|
|
383
|
+
// esptool-js only honours eraseAll on the stub path (esploader.js:
|
|
384
|
+
// `if (this.IS_STUB === true && options.eraseAll === true)`). Silently
|
|
385
|
+
// skipping it would hand back a board still carrying the previous owner's
|
|
386
|
+
// Wi-Fi credentials and pairing token, right after printing "erase" and
|
|
387
|
+
// "MD5 verified".
|
|
388
|
+
throw new Error(`--erase cannot be honoured on ${board.id}: it flashes through the ROM loader\n` +
|
|
389
|
+
' (--no-stub), where esptool-js has no erase command. Re-run without --erase to\n' +
|
|
390
|
+
' write the firmware, or erase the chip with esptool.py.');
|
|
391
|
+
}
|
|
392
|
+
cb.onPhase?.(opts.eraseAll ? 'erase' : 'write');
|
|
393
|
+
await loader.writeFlash({
|
|
394
|
+
fileArray: [{ data: new Uint8Array(image), address: 0x0 }],
|
|
395
|
+
flashMode: geometry.flashMode,
|
|
396
|
+
flashFreq: geometry.flashFreq,
|
|
397
|
+
flashSize: geometry.flashSize,
|
|
398
|
+
// Only honoured on the stub path; a no-op rather than an error on a
|
|
399
|
+
// --no-stub board.
|
|
400
|
+
eraseAll: opts.eraseAll ?? false,
|
|
401
|
+
compress: true,
|
|
402
|
+
reportProgress: (_i, written, total) => cb.onProgress?.(written, total),
|
|
403
|
+
// Hashed AFTER esptool-js patches the flash-params header, which is why
|
|
404
|
+
// this is a callback and not a hash of `image`. A mismatch throws.
|
|
405
|
+
calculateMD5Hash: (patched) => createHash('md5').update(patched).digest('hex'),
|
|
406
|
+
});
|
|
407
|
+
cb.onPhase?.('verify');
|
|
408
|
+
try {
|
|
409
|
+
// Pass the SSOT value straight through. esptool-js's after() handles all
|
|
410
|
+
// four of Esp32ResetAfter natively (esploader.js:1523), so collapsing
|
|
411
|
+
// everything but 'no_reset' into a hard reset would silently override a
|
|
412
|
+
// board that deliberately asks for 'soft_reset' or 'no_reset_stub' — a
|
|
413
|
+
// wrong reset on a board whose flags are an accident record.
|
|
414
|
+
await loader.after(board.after);
|
|
415
|
+
}
|
|
416
|
+
catch (e) {
|
|
417
|
+
// Say it. The write already landed and was verified, so this never fails
|
|
418
|
+
// the command — but the reset is exactly what the boot check below
|
|
419
|
+
// depends on, and swallowing it silently makes a board left parked in the
|
|
420
|
+
// stub byte-identical to a board that booted and stayed quiet.
|
|
421
|
+
cb.log?.(`reset after write failed (${e instanceof Error ? e.message : String(e)}) — the board may need a power cycle`);
|
|
422
|
+
}
|
|
423
|
+
return { chip, mac, flashSize, verdict, bytes: image.length, elapsedMs: Date.now() - t0 };
|
|
424
|
+
}
|
|
425
|
+
finally {
|
|
426
|
+
// Bounded, in this order: disconnect tries to leave the port unlocked, and
|
|
427
|
+
// close releases the fd whether or not it managed to.
|
|
428
|
+
await bounded(transport.disconnect(), 4000, 'transport.disconnect');
|
|
429
|
+
await bounded(device.close(), 4000, 'device.close');
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Reopen the port at 115200 and wait for the firmware's `device_info`.
|
|
434
|
+
*
|
|
435
|
+
* `ulanzi_tc001` MUST SKIP THIS. Its CH340 TX is broken in hardware, so it
|
|
436
|
+
* never answers any serial probe — running this on a TC001 reports a perfectly
|
|
437
|
+
* good flash as a failure. The exception is named in the SSOT's notes, in
|
|
438
|
+
* docs/esp32.md, and in the browser flasher's done-state copy.
|
|
439
|
+
*/
|
|
440
|
+
export const SERIAL_PROBE_UNAVAILABLE = new Set(['ulanzi_tc001']);
|
|
441
|
+
export async function readDeviceIdentity(portPath, timeoutMs = 20_000) {
|
|
442
|
+
const SerialPort = await loadSerialPort();
|
|
443
|
+
if (!SerialPort)
|
|
444
|
+
return null;
|
|
445
|
+
return new Promise((resolve) => {
|
|
446
|
+
// Every handle `done` touches is declared before anything can call it.
|
|
447
|
+
// `done` is reachable from the `error` listener, and a synchronous failure
|
|
448
|
+
// would otherwise run it while `const timer` / `const asker` were still in
|
|
449
|
+
// their temporal dead zone — a ReferenceError instead of the `null` this
|
|
450
|
+
// function promises. Which matters because it runs AFTER a successful
|
|
451
|
+
// write: a throw here reports a good flash as a failure.
|
|
452
|
+
let settled = false;
|
|
453
|
+
let timer = undefined;
|
|
454
|
+
let asker = undefined;
|
|
455
|
+
let port;
|
|
456
|
+
const done = (v) => {
|
|
457
|
+
if (settled)
|
|
458
|
+
return;
|
|
459
|
+
settled = true;
|
|
460
|
+
if (timer)
|
|
461
|
+
clearTimeout(timer);
|
|
462
|
+
if (asker)
|
|
463
|
+
clearInterval(asker);
|
|
464
|
+
try {
|
|
465
|
+
port?.close(() => { });
|
|
466
|
+
}
|
|
467
|
+
catch { /* already closed, or never opened */ }
|
|
468
|
+
resolve(v);
|
|
469
|
+
};
|
|
470
|
+
// Bounded, always: a board that boots into a crash loop writes nothing and
|
|
471
|
+
// an unbounded wait here would hang the command after a SUCCESSFUL write.
|
|
472
|
+
timer = setTimeout(() => done(null), timeoutMs);
|
|
473
|
+
try {
|
|
474
|
+
port = new SerialPort({ path: portPath, baudRate: 115200, autoOpen: false });
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
// A vanished device node (a native-USB board re-enumerating after its
|
|
478
|
+
// reset) throws from the constructor. That is "did not report in", not a
|
|
479
|
+
// failed flash.
|
|
480
|
+
return done(null);
|
|
481
|
+
}
|
|
482
|
+
let buf = '';
|
|
483
|
+
port.on('data', (chunk) => {
|
|
484
|
+
buf += chunk.toString('utf8');
|
|
485
|
+
// Firmware speaks newline-delimited JSON with plain debug lines mixed in.
|
|
486
|
+
for (const line of buf.split('\n').slice(0, -1)) {
|
|
487
|
+
if (!line.trim().startsWith('{'))
|
|
488
|
+
continue;
|
|
489
|
+
try {
|
|
490
|
+
const msg = JSON.parse(line);
|
|
491
|
+
if (msg.type === 'device_info') {
|
|
492
|
+
done({
|
|
493
|
+
board: typeof msg.board === 'string' ? msg.board : undefined,
|
|
494
|
+
version: typeof msg.version === 'string' ? msg.version : undefined,
|
|
495
|
+
buildHash: typeof msg.buildHash === 'string' ? msg.buildHash : undefined,
|
|
496
|
+
});
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
catch { /* a partial or non-JSON line — keep reading */ }
|
|
501
|
+
}
|
|
502
|
+
// Keep only the trailing partial line, so a complete line is parsed once.
|
|
503
|
+
buf = buf.slice(buf.lastIndexOf('\n') + 1);
|
|
504
|
+
// A board stuck printing a panic dump without newlines would otherwise
|
|
505
|
+
// grow this string for the whole timeout. Nothing this long is a protocol
|
|
506
|
+
// line, so drop it rather than accumulate it.
|
|
507
|
+
if (buf.length > 64 * 1024)
|
|
508
|
+
buf = '';
|
|
509
|
+
});
|
|
510
|
+
port.on('error', () => done(null));
|
|
511
|
+
port.open((err) => {
|
|
512
|
+
if (err)
|
|
513
|
+
return done(null);
|
|
514
|
+
port?.write('{"type":"device_info_request"}\n');
|
|
515
|
+
});
|
|
516
|
+
// The board may still be booting when the first ask goes out.
|
|
517
|
+
asker = setInterval(() => {
|
|
518
|
+
if (port?.isOpen)
|
|
519
|
+
port.write('{"type":"device_info_request"}\n');
|
|
520
|
+
}, 3000);
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
//# sourceMappingURL=esp32-flash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esp32-flash.js","sourceRoot":"","sources":["../src/esp32-flash.ts"],"names":[],"mappings":"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"}
|
package/dist/esp32-serial.d.ts
CHANGED
|
@@ -331,8 +331,16 @@ export declare function getSerialReachableBoards(): Array<{
|
|
|
331
331
|
*/
|
|
332
332
|
export declare function handleESP32Wake(): void;
|
|
333
333
|
/**
|
|
334
|
-
*
|
|
334
|
+
* Drop every open serial FD without tearing the bridge down.
|
|
335
|
+
*
|
|
336
|
+
* This is what a flash lease needs and `stopESP32Serial()` is not: the timers
|
|
337
|
+
* stay armed, so once the lease expires the very next poll re-opens whatever is
|
|
338
|
+
* still plugged in — nobody has to remember to resume. Refusing to open (in
|
|
339
|
+
* `pollForDevices`) is only half the job; a port this daemon is ALREADY holding
|
|
340
|
+
* would still block the flasher's own open, and on macOS two readers on one TTY
|
|
341
|
+
* steal each other's bytes rather than failing cleanly.
|
|
335
342
|
*/
|
|
343
|
+
export declare function releaseESP32SerialPorts(reason: string): number;
|
|
336
344
|
export declare function stopESP32Serial(): void;
|
|
337
345
|
/**
|
|
338
346
|
* Get number of connected ESP32 devices.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esp32-serial.d.ts","sourceRoot":"","sources":["../src/esp32-serial.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EASL,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,IAAI,CAAC;AAGZ,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"esp32-serial.d.ts","sourceRoot":"","sources":["../src/esp32-serial.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EASL,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,IAAI,CAAC;AAGZ,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAKjH,0CAA0C;AAC1C,eAAO,MAAM,mBAAmB,UAM/B,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,gBAAgB,UAG5B,CAAC;AA0CF;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAM1F;AAUD,0CAA0C;AAC1C,eAAO,MAAM,qBAAqB,QAAwC,CAAC;AAkB3E,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE;QACV,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B;;8EAEsE;QACtE,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,0EAA0E;QAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,iEAAiE;QACjE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,GAAG,IAAI,CAAC;IACT;;;+CAG2C;IAC3C,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB;+EAC2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB,EAAE,MAAM,CAAC;IAChC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;IACjD;;;8CAG0C;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAkED;;;;GAIG;AACH,0CAA0C;AAI1C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;;;;;;;;GAWG;AACH;;;0EAG0E;AAC1E,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD;;yCAEyC;AACzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAU3D;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,CAoCzE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,GAAG,WAAW,CAgJ9G;AA4LD,0CAA0C;AAC1C,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG9D;AAkBD,0CAA0C;AAC1C,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAgB9E;AAOD;4EAC4E;AAC5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAE5E;AACD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,IAAI,CAEvF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GACzD,IAAI,CAEN;AAED;oDACoD;AACpD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,OAAO,CAK3F;AAED;mEACmE;AACnE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIhE;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGxE;AAED,qFAAqF;AACrF,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAI/C;AAED,gFAAgF;AAChF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAI7D;AAED,0CAA0C;AAC1C,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CA+F3E;AAoMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAE9E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAE9E;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAErF;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAErF;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,WAAW,EAAE,GAAG,IAAI,CAEhF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,KAAK,IAAI,GAAG,IAAI,CAE7F;AAsGD;;;;;GAKG;AACH,0CAA0C;AAC1C,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAErE;AAED;;;;;;;;GAQG;AACH,0CAA0C;AAC1C,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,YAAY,GAAG,YAAY,GAAG,aAAa,CAAC,EAClF,GAAG,SAAa,GACf,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,0CAA0C;AAC1C,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC,EAClE,GAAG,SAAa,GACf,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,0CAA0C;AAC1C,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,WAAW,GAAG,iBAAiB,GAAG,wBAAwB,GAAG,yBAAyB,CAAC,EACpH,GAAG,SAAa,GACf,OAAO,CAKT;AAQD,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAG/E;AAED,kFAAkF;AAClF,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAED;mFACmF;AACnF,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAM5D;AAgFD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAgCvC;AAgGD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAqBvD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAOlF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,CAUxE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAU1E;AAED,0CAA0C;AAC1C,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,WAAW,GAAG,YAAY,GAAG,eAAe,CAAC,EAC1E,KAAK,EAAE,MAAM,GACZ,OAAO,CAQT;AAED,0CAA0C;AAC1C,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,WAAW,GAAG,YAAY,GAAG,eAAe,CAAC,GAAG,OAAO,CAiB3H;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAQD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,IAAI,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAUhF;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAatC;AAyBD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoB9D;AAED,wBAAgB,eAAe,IAAI,IAAI,CAgBtC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAG7C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAGxC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,KAAK,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC,CA+BD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAKlD"}
|