@agentdeck/bridge 1.0.22 → 1.0.24

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.
Files changed (62) hide show
  1. package/dist/apme/activity-history.d.ts +59 -0
  2. package/dist/apme/activity-history.d.ts.map +1 -0
  3. package/dist/apme/activity-history.js +265 -0
  4. package/dist/apme/activity-history.js.map +1 -0
  5. package/dist/apme/dashboard-html.d.ts.map +1 -1
  6. package/dist/apme/dashboard-html.js +40 -6
  7. package/dist/apme/dashboard-html.js.map +1 -1
  8. package/dist/apme/http.d.ts +1 -0
  9. package/dist/apme/http.d.ts.map +1 -1
  10. package/dist/apme/http.js +9 -0
  11. package/dist/apme/http.js.map +1 -1
  12. package/dist/apme/runner.d.ts +20 -0
  13. package/dist/apme/runner.d.ts.map +1 -1
  14. package/dist/apme/runner.js +57 -0
  15. package/dist/apme/runner.js.map +1 -1
  16. package/dist/apme/settings.d.ts +21 -4
  17. package/dist/apme/settings.d.ts.map +1 -1
  18. package/dist/apme/settings.js +29 -5
  19. package/dist/apme/settings.js.map +1 -1
  20. package/dist/apme/store.d.ts +7 -0
  21. package/dist/apme/store.d.ts.map +1 -1
  22. package/dist/apme/store.js +35 -0
  23. package/dist/apme/store.js.map +1 -1
  24. package/dist/cli.d.ts.map +1 -1
  25. package/dist/cli.js +248 -13
  26. package/dist/cli.js.map +1 -1
  27. package/dist/daemon-server.d.ts.map +1 -1
  28. package/dist/daemon-server.js +100 -4
  29. package/dist/daemon-server.js.map +1 -1
  30. package/dist/daemon-takeover.d.ts +3 -0
  31. package/dist/daemon-takeover.d.ts.map +1 -1
  32. package/dist/daemon-takeover.js +5 -0
  33. package/dist/daemon-takeover.js.map +1 -1
  34. package/dist/daemon.js +1 -1
  35. package/dist/esp32-flash-lease.d.ts +47 -0
  36. package/dist/esp32-flash-lease.d.ts.map +1 -0
  37. package/dist/esp32-flash-lease.js +84 -0
  38. package/dist/esp32-flash-lease.js.map +1 -0
  39. package/dist/esp32-flash-transport.d.ts +90 -0
  40. package/dist/esp32-flash-transport.d.ts.map +1 -0
  41. package/dist/esp32-flash-transport.js +157 -0
  42. package/dist/esp32-flash-transport.js.map +1 -0
  43. package/dist/esp32-flash.d.ts +171 -0
  44. package/dist/esp32-flash.d.ts.map +1 -0
  45. package/dist/esp32-flash.js +539 -0
  46. package/dist/esp32-flash.js.map +1 -0
  47. package/dist/esp32-serial.d.ts +9 -1
  48. package/dist/esp32-serial.d.ts.map +1 -1
  49. package/dist/esp32-serial.js +74 -1
  50. package/dist/esp32-serial.js.map +1 -1
  51. package/dist/esptool-js-node.d.ts +17 -0
  52. package/dist/esptool-js-node.d.ts.map +1 -0
  53. package/dist/esptool-js-node.js +17 -0
  54. package/dist/esptool-js-node.js.map +1 -0
  55. package/dist/review-runner.d.ts.map +1 -1
  56. package/dist/review-runner.js +27 -9
  57. package/dist/review-runner.js.map +1 -1
  58. package/dist/timeline-summarizer.d.ts +7 -2
  59. package/dist/timeline-summarizer.d.ts.map +1 -1
  60. package/dist/timeline-summarizer.js +13 -69
  61. package/dist/timeline-summarizer.js.map +1 -1
  62. package/package.json +6 -4
@@ -43,6 +43,9 @@ export interface TakeoverDeps {
43
43
  shutdown: (port: number) => Promise<void>;
44
44
  waitForExit: (port: number, timeoutMs: number) => Promise<boolean>;
45
45
  waitForBindable: (port: number, timeoutMs: number) => Promise<boolean>;
46
+ /** Best-effort derived APME projection capture before the Swift listener
47
+ * disappears. Never blocks takeover on failure. */
48
+ captureActivity?: (port: number, token: unknown) => Promise<boolean>;
46
49
  }
47
50
  export type TakeoverOutcome =
48
51
  /** Nothing in the way (or it yielded) — go bind. */
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-takeover.d.ts","sourceRoot":"","sources":["../src/daemon-takeover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAGxE,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,kBAAkB,CAAC;IACnE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,2DAA2D;IAC3D,UAAU,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IACxC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE;AAED,MAAM,MAAM,eAAe;AACzB,oDAAoD;AAClD,SAAS;AACX,2DAA2D;GACzD,iBAAiB;AACnB,0EAA0E;GACxE,QAAQ,CAAC;AAEb;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,EAC3C,SAAS,GAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,kBAAuC,GACrF,OAAO,CAET;AASD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,EACnF,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,eAAe,CAAC,CAmG1B"}
1
+ {"version":3,"file":"daemon-takeover.d.ts","sourceRoot":"","sources":["../src/daemon-takeover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAGxE,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,kBAAkB,CAAC;IACnE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,2DAA2D;IAC3D,UAAU,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IACxC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnE,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvE;wDACoD;IACpD,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACtE;AAED,MAAM,MAAM,eAAe;AACzB,oDAAoD;AAClD,SAAS;AACX,2DAA2D;GACzD,iBAAiB;AACnB,0EAA0E;GACxE,QAAQ,CAAC;AAEb;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,EAC3C,SAAS,GAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,kBAAuC,GACrF,OAAO,CAET;AASD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,EACnF,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,eAAe,CAAC,CAwG1B"}
@@ -81,6 +81,11 @@ export async function negotiateIncumbentDaemon(args, deps) {
81
81
  log(`Daemon already running on port ${port}. Use 'agentdeck daemon stop' first.`);
82
82
  return 'already-running';
83
83
  }
84
+ if (deps.captureActivity) {
85
+ const captured = await deps.captureActivity(port, incumbent.pairingToken);
86
+ if (captured)
87
+ log(`Merged the app daemon's activity history into the CLI dashboard cache.`);
88
+ }
84
89
  // Reverse two-tier upgrade path: the macOS app may already own the canonical
85
90
  // port with its in-process Swift daemon (Tier 1 — limited: no ADB devices,
86
91
  // no subscription usage, …). A plain "already running → exit" would strand
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-takeover.js","sourceRoot":"","sources":["../src/daemon-takeover.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon-takeover.js","sourceRoot":"","sources":["../src/daemon-takeover.ts"],"names":[],"mappings":"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"}
package/dist/daemon.js CHANGED
@@ -17,7 +17,7 @@ const program = new Command();
17
17
  program
18
18
  .name('agentdeck')
19
19
  .description('AgentDeck daemon (legacy entry point — use `agentdeck daemon` instead)')
20
- .version('1.0.22');
20
+ .version('1.0.24');
21
21
  program
22
22
  .command('start', { isDefault: true })
23
23
  .description('Start monitoring daemon')
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The serial-suspend lease: "nobody but the flasher may open a serial port
3
+ * until <when>".
4
+ *
5
+ * WHY IT IS A FILE AND NOT A VARIABLE. The recorded failure this exists to fix
6
+ * was not the daemon we asked to stand down — it was the daemon that came back.
7
+ * An in-process pause dies with the process; a respawn (LaunchAgent, a user
8
+ * re-running `daemon start`, the app relaunching) opens every port again and
9
+ * DTR-resets the board mid-write. A lease on disk survives that, because the
10
+ * respawned daemon reads it before its first poll.
11
+ *
12
+ * WHY EXPIRY IS ENFORCED ON READ, NEVER BY A TIMER. Same rule the pairing
13
+ * window follows. A timer on a laptop that sleeps fires late, and a late timer
14
+ * extends the suspension past what was promised — the daemon stays deaf to
15
+ * every board for as long as the machine was asleep. Reading the clock at the
16
+ * point of use cannot do that, and it also self-heals when the CLI is killed
17
+ * mid-flash: nothing has to run to end the lease, it simply stops being true.
18
+ *
19
+ * HONEST GAP: the sandboxed Swift daemon cannot read `~/.agentdeck`, so a lease
20
+ * written here does not stop it. That is why the CLI also runs an `lsof`
21
+ * pre-check and refuses to start when a non-AgentDeck process holds the port,
22
+ * and why it verifies after writing rather than trusting the suspension.
23
+ */
24
+ export interface FlashLease {
25
+ /** epoch ms after which the lease means nothing */
26
+ until: number;
27
+ /** who asked, for a human reading the file or the log */
28
+ reason: string;
29
+ /** pid of the requester, informational only — never a liveness test */
30
+ pid?: number;
31
+ board?: string;
32
+ }
33
+ /** Clamp, so a caller cannot suspend the daemon's device layer indefinitely. */
34
+ export declare const LEASE_MIN_SECONDS = 1;
35
+ export declare const LEASE_MAX_SECONDS = 900;
36
+ export declare function leaseFile(): string;
37
+ export declare function clampLeaseSeconds(seconds: unknown): number;
38
+ /**
39
+ * The lease, or null. Expiry is applied HERE — the only place that reads it —
40
+ * so no caller can observe an expired lease as active.
41
+ */
42
+ export declare function readLease(now?: number, file?: string): FlashLease | null;
43
+ export declare function serialSuspended(now?: number): boolean;
44
+ export declare function writeLease(lease: FlashLease, file?: string): FlashLease;
45
+ /** Idempotent: resuming when nothing is suspended is a success, not an error. */
46
+ export declare function clearLease(file?: string): void;
47
+ //# sourceMappingURL=esp32-flash-lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esp32-flash-lease.d.ts","sourceRoot":"","sources":["../src/esp32-flash-lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAI1D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,SAAa,EAAE,IAAI,SAAc,GAAG,UAAU,GAAG,IAAI,CAajF;AAED,wBAAgB,eAAe,CAAC,GAAG,SAAa,GAAG,OAAO,CAEzD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,SAAc,GAAG,UAAU,CAS5E;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,SAAc,GAAG,IAAI,CAMnD"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The serial-suspend lease: "nobody but the flasher may open a serial port
3
+ * until <when>".
4
+ *
5
+ * WHY IT IS A FILE AND NOT A VARIABLE. The recorded failure this exists to fix
6
+ * was not the daemon we asked to stand down — it was the daemon that came back.
7
+ * An in-process pause dies with the process; a respawn (LaunchAgent, a user
8
+ * re-running `daemon start`, the app relaunching) opens every port again and
9
+ * DTR-resets the board mid-write. A lease on disk survives that, because the
10
+ * respawned daemon reads it before its first poll.
11
+ *
12
+ * WHY EXPIRY IS ENFORCED ON READ, NEVER BY A TIMER. Same rule the pairing
13
+ * window follows. A timer on a laptop that sleeps fires late, and a late timer
14
+ * extends the suspension past what was promised — the daemon stays deaf to
15
+ * every board for as long as the machine was asleep. Reading the clock at the
16
+ * point of use cannot do that, and it also self-heals when the CLI is killed
17
+ * mid-flash: nothing has to run to end the lease, it simply stops being true.
18
+ *
19
+ * HONEST GAP: the sandboxed Swift daemon cannot read `~/.agentdeck`, so a lease
20
+ * written here does not stop it. That is why the CLI also runs an `lsof`
21
+ * pre-check and refuses to start when a non-AgentDeck process holds the port,
22
+ * and why it verifies after writing rather than trusting the suspension.
23
+ */
24
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'fs';
25
+ import { dirname, join } from 'path';
26
+ import { getDataDir } from './session-registry.js';
27
+ import { debug } from './logger.js';
28
+ /** Clamp, so a caller cannot suspend the daemon's device layer indefinitely. */
29
+ export const LEASE_MIN_SECONDS = 1;
30
+ export const LEASE_MAX_SECONDS = 900;
31
+ export function leaseFile() {
32
+ return join(getDataDir(), 'esp32-flash-lease.json');
33
+ }
34
+ export function clampLeaseSeconds(seconds) {
35
+ const n = Number(seconds);
36
+ if (!Number.isFinite(n))
37
+ return LEASE_MIN_SECONDS;
38
+ return Math.max(LEASE_MIN_SECONDS, Math.min(LEASE_MAX_SECONDS, Math.floor(n)));
39
+ }
40
+ /**
41
+ * The lease, or null. Expiry is applied HERE — the only place that reads it —
42
+ * so no caller can observe an expired lease as active.
43
+ */
44
+ export function readLease(now = Date.now(), file = leaseFile()) {
45
+ try {
46
+ if (!existsSync(file))
47
+ return null;
48
+ const raw = JSON.parse(readFileSync(file, 'utf8'));
49
+ const until = Number(raw.until);
50
+ if (!Number.isFinite(until) || until <= now)
51
+ return null;
52
+ return { until, reason: String(raw.reason ?? 'unknown'), pid: raw.pid, board: raw.board };
53
+ }
54
+ catch {
55
+ // A corrupt lease means "no lease". Failing open is correct: the cost is a
56
+ // reset board during a flash that is probably not running; failing closed
57
+ // would leave every device permanently unreachable behind a bad file.
58
+ return null;
59
+ }
60
+ }
61
+ export function serialSuspended(now = Date.now()) {
62
+ return readLease(now) !== null;
63
+ }
64
+ export function writeLease(lease, file = leaseFile()) {
65
+ mkdirSync(dirname(file), { recursive: true });
66
+ // tmp+rename, like every other file this daemon owns: a torn lease read as
67
+ // corrupt is a lease that silently is not protecting the write in flight.
68
+ const tmp = `${file}.tmp`;
69
+ writeFileSync(tmp, `${JSON.stringify(lease, null, 2)}\n`);
70
+ renameSync(tmp, file);
71
+ debug('ESP32', `flash lease until ${new Date(lease.until).toISOString()} (${lease.reason})`);
72
+ return lease;
73
+ }
74
+ /** Idempotent: resuming when nothing is suspended is a success, not an error. */
75
+ export function clearLease(file = leaseFile()) {
76
+ try {
77
+ if (existsSync(file))
78
+ unlinkSync(file);
79
+ }
80
+ catch {
81
+ // Best effort. An unremovable lease still expires on its own clock.
82
+ }
83
+ }
84
+ //# sourceMappingURL=esp32-flash-lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esp32-flash-lease.js","sourceRoot":"","sources":["../src/esp32-flash-lease.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * A Web Serial-shaped port over `serialport`, so the CLI can drive esptool-js.
3
+ *
4
+ * WHY A SHIM AND NOT AN EXTENSION OF `esp32-serial.ts`. That module opens a raw
5
+ * fd and configures the line with `stty`, which can set baud and framing but
6
+ * **cannot touch DTR or RTS** — those need `ioctl(TIOCMSET)`. DTR/RTS *are* the
7
+ * ROM download-mode entry sequence, so there is no path from the existing
8
+ * serial code to a flasher. `serialport`'s `set({dtr, rts})` is the missing
9
+ * primitive, and once you have it, esptool-js needs only six members of a Web
10
+ * Serial port — open/close/readable/writable/setSignals/getInfo — which is what
11
+ * this class is.
12
+ *
13
+ * This exact adapter was what made the Phase 0 hardware spike possible: the
14
+ * browser's `requestPort()` opens a native chooser no automation can drive, so
15
+ * seven boards were measured headlessly through this code path before a byte
16
+ * was ever written. It is not scaffolding that got reused; it is the thing that
17
+ * was validated.
18
+ *
19
+ * `serialport` is an OPTIONAL dependency (native module, same class as
20
+ * `node-pty` / `better-sqlite3` / `@resvg/resvg-js`), so every entry point here
21
+ * has to survive its absence with an actionable message rather than a
22
+ * MODULE_NOT_FOUND stack.
23
+ */
24
+ /** Loaded lazily so importing this module never fails on a machine without it. */
25
+ type SerialPortCtor = typeof import('serialport').SerialPort;
26
+ export declare function loadSerialPort(): Promise<SerialPortCtor | null>;
27
+ /** @internal test seam — lets the absent-module path run without uninstalling anything. */
28
+ export declare function __setSerialPortForTests(ctor: SerialPortCtor | null | undefined): void;
29
+ export interface PortCandidate {
30
+ path: string;
31
+ usbVendorId?: number;
32
+ usbProductId?: number;
33
+ manufacturer?: string;
34
+ }
35
+ export declare function listCandidatePorts(): Promise<PortCandidate[]>;
36
+ interface OpenOpts {
37
+ baudRate: number;
38
+ dataBits?: number;
39
+ stopBits?: number;
40
+ parity?: string;
41
+ bufferSize?: number;
42
+ flowControl?: string;
43
+ }
44
+ /**
45
+ * The six members esptool-js touches, and nothing else. Structurally compatible
46
+ * with `SerialPort` from the Web Serial types; cast at the call site.
47
+ */
48
+ export declare class NodeWebSerialPort {
49
+ private readonly path;
50
+ private readonly info;
51
+ private readonly ctor?;
52
+ private port?;
53
+ private webReadable?;
54
+ private webWritable?;
55
+ constructor(path: string, info?: {
56
+ usbVendorId?: number;
57
+ usbProductId?: number;
58
+ }, ctor?: SerialPortCtor | undefined);
59
+ getInfo(): {
60
+ usbVendorId?: number;
61
+ usbProductId?: number;
62
+ };
63
+ get readable(): ReadableStream<Uint8Array> | null;
64
+ get writable(): WritableStream<Uint8Array> | null;
65
+ open(opts: OpenOpts): Promise<void>;
66
+ /**
67
+ * ALWAYS WRITE BOTH LINES. This is the single most expensive thing the spike
68
+ * learned.
69
+ *
70
+ * Web Serial lets a caller move one signal and leave the other alone;
71
+ * `serialport`'s `set()` applies its OWN defaults to whatever you omit, so a
72
+ * single-signal call silently moves the other line too. esptool-js's
73
+ * `Transport.setRTS()` re-sends DTR immediately after RTS (a usbser.sys
74
+ * work-around), so the clobber lands on every reset strobe and the board
75
+ * never enters the ROM bootloader. The symptom is only ever "failed to
76
+ * connect" — nothing points at the adapter. Every strategy failed on the
77
+ * first probe run for exactly this reason.
78
+ *
79
+ * So the two lines are held here and both are written every time.
80
+ */
81
+ private dtr;
82
+ private rts;
83
+ setSignals(signals: {
84
+ dataTerminalReady?: boolean;
85
+ requestToSend?: boolean;
86
+ }): Promise<void>;
87
+ close(): Promise<void>;
88
+ }
89
+ export {};
90
+ //# sourceMappingURL=esp32-flash-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esp32-flash-transport.d.ts","sourceRoot":"","sources":["../src/esp32-flash-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,kFAAkF;AAClF,KAAK,cAAc,GAAG,cAAc,YAAY,EAAE,UAAU,CAAC;AAI7D,wBAAsB,cAAc,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CASrE;AAED,2FAA2F;AAC3F,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAErF;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAYD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAYnE;AAED,UAAU,QAAQ;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,iBAAiB;IAM1B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IAPxB,OAAO,CAAC,IAAI,CAAC,CAA+B;IAC5C,OAAO,CAAC,WAAW,CAAC,CAA6B;IACjD,OAAO,CAAC,WAAW,CAAC,CAA6B;gBAG9B,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO,EAC1D,IAAI,CAAC,EAAE,cAAc,YAAA;IAGxC,OAAO,IAAI;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;IAI1D,IAAI,QAAQ,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAEhD;IAED,IAAI,QAAQ,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAEhD;IAEK,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BzC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,GAAG,CAAS;IAEd,UAAU,CAAC,OAAO,EAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5F,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAW7B"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * A Web Serial-shaped port over `serialport`, so the CLI can drive esptool-js.
3
+ *
4
+ * WHY A SHIM AND NOT AN EXTENSION OF `esp32-serial.ts`. That module opens a raw
5
+ * fd and configures the line with `stty`, which can set baud and framing but
6
+ * **cannot touch DTR or RTS** — those need `ioctl(TIOCMSET)`. DTR/RTS *are* the
7
+ * ROM download-mode entry sequence, so there is no path from the existing
8
+ * serial code to a flasher. `serialport`'s `set({dtr, rts})` is the missing
9
+ * primitive, and once you have it, esptool-js needs only six members of a Web
10
+ * Serial port — open/close/readable/writable/setSignals/getInfo — which is what
11
+ * this class is.
12
+ *
13
+ * This exact adapter was what made the Phase 0 hardware spike possible: the
14
+ * browser's `requestPort()` opens a native chooser no automation can drive, so
15
+ * seven boards were measured headlessly through this code path before a byte
16
+ * was ever written. It is not scaffolding that got reused; it is the thing that
17
+ * was validated.
18
+ *
19
+ * `serialport` is an OPTIONAL dependency (native module, same class as
20
+ * `node-pty` / `better-sqlite3` / `@resvg/resvg-js`), so every entry point here
21
+ * has to survive its absence with an actionable message rather than a
22
+ * MODULE_NOT_FOUND stack.
23
+ */
24
+ import { Readable, Writable } from 'node:stream';
25
+ let cached;
26
+ export async function loadSerialPort() {
27
+ if (cached !== undefined)
28
+ return cached;
29
+ try {
30
+ const mod = await import('serialport');
31
+ cached = mod.SerialPort;
32
+ }
33
+ catch {
34
+ cached = null;
35
+ }
36
+ return cached;
37
+ }
38
+ /** @internal test seam — lets the absent-module path run without uninstalling anything. */
39
+ export function __setSerialPortForTests(ctor) {
40
+ cached = ctor;
41
+ }
42
+ /**
43
+ * macOS exposes each USB serial device twice: `/dev/tty.*` blocks on open until
44
+ * DCD asserts, `/dev/cu.*` does not. Only the callout node is usable here.
45
+ */
46
+ const toCallout = (p) => p.replace('/dev/tty.', '/dev/cu.');
47
+ /** Same predicate the serial bridge uses, so both agree on what is a candidate. */
48
+ const CANDIDATE = /usbserial|wchusbserial|usbmodem|ttyUSB|ttyACM/;
49
+ const EXCLUDE = /Bluetooth|WLAN|debug/i;
50
+ export async function listCandidatePorts() {
51
+ const SerialPort = await loadSerialPort();
52
+ if (!SerialPort)
53
+ return [];
54
+ const list = await SerialPort.list();
55
+ return list
56
+ .filter((p) => CANDIDATE.test(p.path) && !EXCLUDE.test(p.path))
57
+ .map((p) => ({
58
+ path: toCallout(p.path),
59
+ usbVendorId: p.vendorId ? Number.parseInt(p.vendorId, 16) : undefined,
60
+ usbProductId: p.productId ? Number.parseInt(p.productId, 16) : undefined,
61
+ manufacturer: p.manufacturer,
62
+ }));
63
+ }
64
+ /**
65
+ * The six members esptool-js touches, and nothing else. Structurally compatible
66
+ * with `SerialPort` from the Web Serial types; cast at the call site.
67
+ */
68
+ export class NodeWebSerialPort {
69
+ path;
70
+ info;
71
+ ctor;
72
+ port;
73
+ webReadable;
74
+ webWritable;
75
+ constructor(path, info = {}, ctor) {
76
+ this.path = path;
77
+ this.info = info;
78
+ this.ctor = ctor;
79
+ }
80
+ getInfo() {
81
+ return this.info;
82
+ }
83
+ get readable() {
84
+ return this.webReadable ?? null;
85
+ }
86
+ get writable() {
87
+ return this.webWritable ?? null;
88
+ }
89
+ async open(opts) {
90
+ const SerialPort = this.ctor ?? (await loadSerialPort());
91
+ if (!SerialPort)
92
+ throw new Error('serialport is not installed');
93
+ // A fresh handle per open: Transport.connect() re-opens at a new baud, and
94
+ // reusing the streams across a close would hand back a locked reader.
95
+ await this.close();
96
+ await new Promise((resolve, reject) => {
97
+ this.port = new SerialPort({
98
+ path: this.path,
99
+ baudRate: opts.baudRate,
100
+ dataBits: (opts.dataBits ?? 8),
101
+ stopBits: (opts.stopBits ?? 1),
102
+ parity: (opts.parity ?? 'none'),
103
+ autoOpen: false,
104
+ // Do NOT let the driver assert DTR/RTS on open. esptool drives the
105
+ // reset sequence itself, and an implicit strobe here resets the board
106
+ // at a moment the chosen strategy is not expecting.
107
+ hupcl: false,
108
+ }, (err) => { if (err)
109
+ reject(err); });
110
+ this.port.open((err) => (err ? reject(err) : resolve()));
111
+ });
112
+ this.webReadable = Readable.toWeb(this.port);
113
+ this.webWritable = Writable.toWeb(this.port);
114
+ }
115
+ /* --------------------------------------------------------------- signals */
116
+ /**
117
+ * ALWAYS WRITE BOTH LINES. This is the single most expensive thing the spike
118
+ * learned.
119
+ *
120
+ * Web Serial lets a caller move one signal and leave the other alone;
121
+ * `serialport`'s `set()` applies its OWN defaults to whatever you omit, so a
122
+ * single-signal call silently moves the other line too. esptool-js's
123
+ * `Transport.setRTS()` re-sends DTR immediately after RTS (a usbser.sys
124
+ * work-around), so the clobber lands on every reset strobe and the board
125
+ * never enters the ROM bootloader. The symptom is only ever "failed to
126
+ * connect" — nothing points at the adapter. Every strategy failed on the
127
+ * first probe run for exactly this reason.
128
+ *
129
+ * So the two lines are held here and both are written every time.
130
+ */
131
+ dtr = false;
132
+ rts = false;
133
+ async setSignals(signals) {
134
+ const p = this.port;
135
+ if (!p?.isOpen)
136
+ return;
137
+ if (signals.dataTerminalReady !== undefined)
138
+ this.dtr = signals.dataTerminalReady;
139
+ if (signals.requestToSend !== undefined)
140
+ this.rts = signals.requestToSend;
141
+ await new Promise((resolve, reject) => p.set({ dtr: this.dtr, rts: this.rts }, (e) => (e ? reject(e) : resolve())));
142
+ }
143
+ async close() {
144
+ const p = this.port;
145
+ this.webReadable = undefined;
146
+ this.webWritable = undefined;
147
+ this.port = undefined;
148
+ if (!p)
149
+ return;
150
+ await new Promise((resolve) => {
151
+ if (!p.isOpen)
152
+ return resolve();
153
+ p.close(() => resolve());
154
+ });
155
+ }
156
+ }
157
+ //# sourceMappingURL=esp32-flash-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esp32-flash-transport.js","sourceRoot":"","sources":["../src/esp32-flash-transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,171 @@
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 { type Esp32BoardSpec, type Esp32PreflightVerdict } from '@agentdeck/shared';
19
+ export declare const GITHUB_REPO = "puritysb/AgentDeck";
20
+ export declare function resolveFlashBoard(target: string): Esp32BoardSpec;
21
+ export interface ManifestArtifact {
22
+ file: string;
23
+ size: number;
24
+ sha256: string;
25
+ offset: string;
26
+ }
27
+ export interface ManifestBoardEntry {
28
+ id: string;
29
+ chipFamily: string;
30
+ flashSize: string;
31
+ flashMode: string;
32
+ flashFreq: string;
33
+ uploadBaud: number;
34
+ merged?: ManifestArtifact;
35
+ }
36
+ export interface ReleaseManifest {
37
+ schema: number;
38
+ release: string;
39
+ firmwareVersion: string;
40
+ boards: ManifestBoardEntry[];
41
+ }
42
+ /**
43
+ * Every published `esp32-v*` tag, newest first.
44
+ *
45
+ * PAGED, because a single page is a silent cap. `per_page` maxes at 100 and
46
+ * this repo cuts ~6 tags a round across its channels, so once ~100 releases
47
+ * accumulate after the newest esp32 cut, one page stops containing it — and the
48
+ * damage is not "no answer" but a WRONG one: the existence check would report a
49
+ * genuinely published version as unpublished and quietly fall back to an older
50
+ * release. Stops at the first page that yields no esp32 tag once some are
51
+ * already known, so the common case is still one request.
52
+ */
53
+ export declare function listFirmwareTags(maxPages?: number): Promise<string[]>;
54
+ /** Newest `esp32-v*` tag, or undefined when the repo has none. */
55
+ export declare function latestFirmwareTag(): Promise<string | undefined>;
56
+ /**
57
+ * Which release a bare `agentdeck esp32 flash <board>` takes firmware from.
58
+ *
59
+ * TWO RULES, IN THIS ORDER, AND NEITHER WORKS ALONE. The checkout's
60
+ * `FIRMWARE_VERSION` names the release this source tree belongs to — but it is
61
+ * bumped BEFORE the tag is pushed, so during that window it names a release
62
+ * that does not exist yet. Taking it unconditionally is how the first command
63
+ * in the docs came to fail from every checkout the moment the version was
64
+ * bumped (and the 404 it produced was indistinguishable from "this release has
65
+ * no manifest", so it also misdiagnosed itself).
66
+ *
67
+ * Deliberately the same shape as `resolveTag` in
68
+ * `scripts/fetch-flash-firmware.mjs`. That one runs in CI with `gh`; this one
69
+ * runs on a user's machine with `fetch`. Same rules, same reported `source`.
70
+ */
71
+ export declare function pickFirmwareTag(configVersion: string | undefined, published: readonly string[]): {
72
+ tag: string;
73
+ source: 'config' | 'latest';
74
+ };
75
+ export declare function firmwareVersionFromCheckout(configH: string): string | undefined;
76
+ export declare function firmwareCacheDir(tag: string): string;
77
+ export interface ResolveFirmwareOptions {
78
+ tag?: string;
79
+ /** an explicit .bin — skips the download entirely, mirroring esp32-ota's -f */
80
+ firmwarePath?: string;
81
+ /** fail instead of reaching the network */
82
+ offline?: boolean;
83
+ /** the repo checkout's esp32/src/config.h, when running from a checkout */
84
+ checkoutConfigH?: string;
85
+ log?: (msg: string) => void;
86
+ }
87
+ export interface ResolvedFirmware {
88
+ tag: string;
89
+ image: Buffer;
90
+ /** the manifest entry, when one was used; absent for --firmware */
91
+ entry?: ManifestBoardEntry;
92
+ source: 'file' | 'cache' | 'download';
93
+ path?: string;
94
+ }
95
+ /**
96
+ * Get the merged image for a board, verifying its sha256 EVERY time — on a
97
+ * fresh download and on every cache hit. The cache key proves which release a
98
+ * file came from, never that its bits are still intact, and a bit-rotted cached
99
+ * image is a bricked board.
100
+ */
101
+ export declare function resolveFirmware(board: Esp32BoardSpec, opts?: ResolveFirmwareOptions): Promise<ResolvedFirmware>;
102
+ export interface PortHolder {
103
+ command: string;
104
+ pid: number;
105
+ }
106
+ /**
107
+ * Three answers, not two — because this is the ONLY guard against the holder
108
+ * the lease provably cannot reach (the sandboxed Swift daemon cannot read
109
+ * `~/.agentdeck`).
110
+ *
111
+ * `lsof` exits non-zero when nothing holds the file, so a failed run really is
112
+ * the common "free" case. But it ALSO exits non-zero when it is not installed
113
+ * (a minimal Linux container), when the 5s timeout fires, and on EPERM — and
114
+ * collapsing those into `[]` launders "I could not look" into "nobody is
115
+ * holding it", which is the exact trap `esp32FlashIdIsUsable` exists to avoid
116
+ * on the flash-size axis, inverted to the permissive direction.
117
+ */
118
+ export type PortHolderScan = {
119
+ known: true;
120
+ holders: PortHolder[];
121
+ } | {
122
+ known: false;
123
+ reason: string;
124
+ };
125
+ export declare function parseLsofHolders(stdout: string): PortHolder[];
126
+ export declare function scanPortHolders(port: string): Promise<PortHolderScan>;
127
+ /** Back-compat convenience: holders, or none when they could not be observed. */
128
+ export declare function whoHoldsPort(port: string): Promise<PortHolder[]>;
129
+ export declare function classifyHolders(holders: PortHolder[]): {
130
+ ours: PortHolder[];
131
+ foreign: PortHolder[];
132
+ };
133
+ export interface FlashProgress {
134
+ onPhase?: (phase: string) => void;
135
+ onProgress?: (written: number, total: number) => void;
136
+ log?: (msg: string) => void;
137
+ }
138
+ export interface FlashOutcome {
139
+ chip: string;
140
+ mac: string;
141
+ flashSize?: string;
142
+ verdict: Esp32PreflightVerdict;
143
+ bytes: number;
144
+ elapsedMs: number;
145
+ }
146
+ /**
147
+ * Connect, identify, refuse-or-write, verify by MD5. Mirrors the browser's
148
+ * `flash.ts` step for step; the two share `esp32PreflightVerdict` so they can
149
+ * never disagree about which board may be written.
150
+ */
151
+ export declare function flashBoard(board: Esp32BoardSpec, portPath: string, image: Buffer, geometry: Pick<ManifestBoardEntry, 'flashMode' | 'flashFreq' | 'flashSize'> & Partial<Pick<ManifestBoardEntry, 'chipFamily'>>, opts?: {
152
+ eraseAll?: boolean;
153
+ baud?: number;
154
+ imageIsFromManifest?: boolean;
155
+ }, cb?: FlashProgress): Promise<FlashOutcome>;
156
+ export interface DeviceIdentity {
157
+ board?: string;
158
+ version?: string;
159
+ buildHash?: string;
160
+ }
161
+ /**
162
+ * Reopen the port at 115200 and wait for the firmware's `device_info`.
163
+ *
164
+ * `ulanzi_tc001` MUST SKIP THIS. Its CH340 TX is broken in hardware, so it
165
+ * never answers any serial probe — running this on a TC001 reports a perfectly
166
+ * good flash as a failure. The exception is named in the SSOT's notes, in
167
+ * docs/esp32.md, and in the browser flasher's done-state copy.
168
+ */
169
+ export declare const SERIAL_PROBE_UNAVAILABLE: Set<string>;
170
+ export declare function readDeviceIdentity(portPath: string, timeoutMs?: number): Promise<DeviceIdentity | null>;
171
+ //# sourceMappingURL=esp32-flash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esp32-flash.d.ts","sourceRoot":"","sources":["../src/esp32-flash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAC;AAM3B,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAIhD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAOhE;AAQD,MAAM,WAAW,gBAAgB;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAChG,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B;AACD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAUD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,SAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkBtE;AAED,kEAAkE;AAClE,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAErE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,CAQ9C;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/E;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAgBD,MAAM,WAAW,sBAAsB;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,cAAc,EACrB,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAmG3B;AASD,MAAM,WAAW,UAAU;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAE5D;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,GACtC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAS7D;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAoB3E;AAED,iFAAiF;AACjF,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGtE;AAKD,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CAKpG;AAID,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAmCD;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC,GACzE,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC,EACjD,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAAO,EAC/E,EAAE,GAAE,aAAkB,GACrB,OAAO,CAAC,YAAY,CAAC,CAkJvB;AAQD,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,aAA4B,CAAC;AAElE,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAS,GACjB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAuEhC"}