@agentdeck/bridge 1.0.24 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +14 -6
  2. package/assets/fonts/NOTICE-PocketSansWorld.md +10 -0
  3. package/assets/fonts/OFL-PocketSansWorld.txt +93 -0
  4. package/assets/fonts/PocketSansWorld_12.cpfont +0 -0
  5. package/assets/fonts/pocket-sans-world.manifest.json +49 -0
  6. package/assets/learning/LICENSE-CC-BY-SA-4.0.txt +10 -0
  7. package/assets/learning/NOTICE.md +33 -0
  8. package/assets/learning/jp-n3-ko.manifest.json +27 -0
  9. package/assets/learning/jp-n3-ko.pdl +0 -0
  10. package/dist/adapters/openclaw.d.ts +74 -4
  11. package/dist/adapters/openclaw.d.ts.map +1 -1
  12. package/dist/adapters/openclaw.js +235 -43
  13. package/dist/adapters/openclaw.js.map +1 -1
  14. package/dist/agent-cli-diagnostics.d.ts +20 -0
  15. package/dist/agent-cli-diagnostics.d.ts.map +1 -0
  16. package/dist/agent-cli-diagnostics.js +100 -0
  17. package/dist/agent-cli-diagnostics.js.map +1 -0
  18. package/dist/apme/adapters/openclaw-hook.d.ts +38 -10
  19. package/dist/apme/adapters/openclaw-hook.d.ts.map +1 -1
  20. package/dist/apme/adapters/openclaw-hook.js +181 -37
  21. package/dist/apme/adapters/openclaw-hook.js.map +1 -1
  22. package/dist/apme/collector.d.ts +55 -2
  23. package/dist/apme/collector.d.ts.map +1 -1
  24. package/dist/apme/collector.js +324 -37
  25. package/dist/apme/collector.js.map +1 -1
  26. package/dist/apme/dashboard-html.d.ts.map +1 -1
  27. package/dist/apme/dashboard-html.js +275 -35
  28. package/dist/apme/dashboard-html.js.map +1 -1
  29. package/dist/apme/http.d.ts.map +1 -1
  30. package/dist/apme/http.js +33 -5
  31. package/dist/apme/http.js.map +1 -1
  32. package/dist/apme/index.d.ts.map +1 -1
  33. package/dist/apme/index.js +6 -2
  34. package/dist/apme/index.js.map +1 -1
  35. package/dist/apme/pareto.d.ts +2 -1
  36. package/dist/apme/pareto.d.ts.map +1 -1
  37. package/dist/apme/pareto.js +15 -4
  38. package/dist/apme/pareto.js.map +1 -1
  39. package/dist/apme/recommend.d.ts +24 -1
  40. package/dist/apme/recommend.d.ts.map +1 -1
  41. package/dist/apme/recommend.js +43 -7
  42. package/dist/apme/recommend.js.map +1 -1
  43. package/dist/apme/store.d.ts +47 -1
  44. package/dist/apme/store.d.ts.map +1 -1
  45. package/dist/apme/store.js +397 -99
  46. package/dist/apme/store.js.map +1 -1
  47. package/dist/bridge-core.d.ts +25 -1
  48. package/dist/bridge-core.d.ts.map +1 -1
  49. package/dist/bridge-core.js +50 -9
  50. package/dist/bridge-core.js.map +1 -1
  51. package/dist/card-feed.d.ts +46 -1
  52. package/dist/card-feed.d.ts.map +1 -1
  53. package/dist/card-feed.js +166 -6
  54. package/dist/card-feed.js.map +1 -1
  55. package/dist/cli.d.ts +56 -0
  56. package/dist/cli.d.ts.map +1 -1
  57. package/dist/cli.js +442 -34
  58. package/dist/cli.js.map +1 -1
  59. package/dist/codex-rate-limits-live.d.ts +180 -10
  60. package/dist/codex-rate-limits-live.d.ts.map +1 -1
  61. package/dist/codex-rate-limits-live.js +475 -22
  62. package/dist/codex-rate-limits-live.js.map +1 -1
  63. package/dist/daemon-build-identity.d.ts +124 -0
  64. package/dist/daemon-build-identity.d.ts.map +1 -0
  65. package/dist/daemon-build-identity.js +310 -0
  66. package/dist/daemon-build-identity.js.map +1 -0
  67. package/dist/daemon-server.d.ts +34 -6
  68. package/dist/daemon-server.d.ts.map +1 -1
  69. package/dist/daemon-server.js +876 -109
  70. package/dist/daemon-server.js.map +1 -1
  71. package/dist/daemon-takeover.d.ts +11 -0
  72. package/dist/daemon-takeover.d.ts.map +1 -1
  73. package/dist/daemon-takeover.js +62 -17
  74. package/dist/daemon-takeover.js.map +1 -1
  75. package/dist/daemon-ws-client.d.ts +1 -0
  76. package/dist/daemon-ws-client.d.ts.map +1 -1
  77. package/dist/daemon-ws-client.js +25 -16
  78. package/dist/daemon-ws-client.js.map +1 -1
  79. package/dist/daemon.js +1 -1
  80. package/dist/daemon.js.map +1 -1
  81. package/dist/esp32-serial.d.ts +18 -0
  82. package/dist/esp32-serial.d.ts.map +1 -1
  83. package/dist/esp32-serial.js +23 -1
  84. package/dist/esp32-serial.js.map +1 -1
  85. package/dist/font-pack.d.ts +15 -0
  86. package/dist/font-pack.d.ts.map +1 -0
  87. package/dist/font-pack.js +75 -0
  88. package/dist/font-pack.js.map +1 -0
  89. package/dist/glance-frame.d.ts.map +1 -1
  90. package/dist/glance-frame.js +5 -1
  91. package/dist/glance-frame.js.map +1 -1
  92. package/dist/hook-codex-sessions.d.ts +3 -1
  93. package/dist/hook-codex-sessions.d.ts.map +1 -1
  94. package/dist/hook-codex-sessions.js +27 -7
  95. package/dist/hook-codex-sessions.js.map +1 -1
  96. package/dist/http-auth-gate.d.ts.map +1 -1
  97. package/dist/http-auth-gate.js +9 -1
  98. package/dist/http-auth-gate.js.map +1 -1
  99. package/dist/index.js +2 -2
  100. package/dist/index.js.map +1 -1
  101. package/dist/learning-pack.d.ts +24 -0
  102. package/dist/learning-pack.d.ts.map +1 -0
  103. package/dist/learning-pack.js +125 -0
  104. package/dist/learning-pack.js.map +1 -0
  105. package/dist/legacy-rearm-ledger.d.ts +56 -0
  106. package/dist/legacy-rearm-ledger.d.ts.map +1 -0
  107. package/dist/legacy-rearm-ledger.js +66 -0
  108. package/dist/legacy-rearm-ledger.js.map +1 -0
  109. package/dist/mdns.d.ts +33 -0
  110. package/dist/mdns.d.ts.map +1 -1
  111. package/dist/mdns.js +92 -3
  112. package/dist/mdns.js.map +1 -1
  113. package/dist/openclaw-session.d.ts.map +1 -1
  114. package/dist/openclaw-session.js +13 -0
  115. package/dist/openclaw-session.js.map +1 -1
  116. package/dist/openclaw-timeline-feed.d.ts +84 -0
  117. package/dist/openclaw-timeline-feed.d.ts.map +1 -0
  118. package/dist/openclaw-timeline-feed.js +162 -0
  119. package/dist/openclaw-timeline-feed.js.map +1 -0
  120. package/dist/openclaw-transcript-timeline.d.ts +103 -0
  121. package/dist/openclaw-transcript-timeline.d.ts.map +1 -0
  122. package/dist/openclaw-transcript-timeline.js +328 -0
  123. package/dist/openclaw-transcript-timeline.js.map +1 -0
  124. package/dist/pairing-knocks.d.ts +80 -0
  125. package/dist/pairing-knocks.d.ts.map +1 -0
  126. package/dist/pairing-knocks.js +312 -0
  127. package/dist/pairing-knocks.js.map +1 -0
  128. package/dist/passive-observer.d.ts +21 -1
  129. package/dist/passive-observer.d.ts.map +1 -1
  130. package/dist/passive-observer.js +37 -3
  131. package/dist/passive-observer.js.map +1 -1
  132. package/dist/pixoo/micro-glyphs.d.ts +4 -0
  133. package/dist/pixoo/micro-glyphs.d.ts.map +1 -1
  134. package/dist/pixoo/micro-glyphs.js +29 -0
  135. package/dist/pixoo/micro-glyphs.js.map +1 -1
  136. package/dist/pixoo/pixoo-font.d.ts.map +1 -1
  137. package/dist/pixoo/pixoo-font.js +3 -1
  138. package/dist/pixoo/pixoo-font.js.map +1 -1
  139. package/dist/pixoo/pixoo-renderer.d.ts +1 -1
  140. package/dist/pixoo/pixoo-renderer.d.ts.map +1 -1
  141. package/dist/pixoo/pixoo-renderer.js +17 -2
  142. package/dist/pixoo/pixoo-renderer.js.map +1 -1
  143. package/dist/pty-manager.d.ts +9 -0
  144. package/dist/pty-manager.d.ts.map +1 -1
  145. package/dist/pty-manager.js +63 -4
  146. package/dist/pty-manager.js.map +1 -1
  147. package/dist/relayed-usage.d.ts +98 -0
  148. package/dist/relayed-usage.d.ts.map +1 -0
  149. package/dist/relayed-usage.js +103 -0
  150. package/dist/relayed-usage.js.map +1 -0
  151. package/dist/session-aggregator.d.ts +3 -0
  152. package/dist/session-aggregator.d.ts.map +1 -1
  153. package/dist/session-aggregator.js.map +1 -1
  154. package/dist/session-registry.d.ts +1 -0
  155. package/dist/session-registry.d.ts.map +1 -1
  156. package/dist/surface-protocol.d.ts +84 -0
  157. package/dist/surface-protocol.d.ts.map +1 -0
  158. package/dist/surface-protocol.js +237 -0
  159. package/dist/surface-protocol.js.map +1 -0
  160. package/dist/timeline-store.d.ts +1 -1
  161. package/dist/timeline-store.d.ts.map +1 -1
  162. package/dist/timeline-store.js +16 -1
  163. package/dist/timeline-store.js.map +1 -1
  164. package/dist/tui/dashboard.d.ts.map +1 -1
  165. package/dist/tui/dashboard.js +8 -1
  166. package/dist/tui/dashboard.js.map +1 -1
  167. package/dist/tui/renderer.d.ts.map +1 -1
  168. package/dist/tui/renderer.js +35 -0
  169. package/dist/tui/renderer.js.map +1 -1
  170. package/dist/weather-config.d.ts +17 -0
  171. package/dist/weather-config.d.ts.map +1 -0
  172. package/dist/weather-config.js +54 -0
  173. package/dist/weather-config.js.map +1 -0
  174. package/dist/weather.d.ts +44 -4
  175. package/dist/weather.d.ts.map +1 -1
  176. package/dist/weather.js +223 -15
  177. package/dist/weather.js.map +1 -1
  178. package/dist/ws-server.d.ts +18 -0
  179. package/dist/ws-server.d.ts.map +1 -1
  180. package/dist/ws-server.js +95 -7
  181. package/dist/ws-server.js.map +1 -1
  182. package/fm-helper/AgentDeckFMHelper.swift +51 -5
  183. package/package.json +4 -3
  184. package/src/timebox/sync_ble.py +35 -16
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Which build of AgentDeck is actually running, and whether it is the newest
3
+ * one on this disk.
4
+ *
5
+ * A dev checkout hands `agentdeck` to the shell as a shim that executes
6
+ * `bridge/dist/cli.js` in the repo, so "the version I am running" is whatever
7
+ * `tsc` last wrote there — a fact with no stamp on it anywhere. Two silent
8
+ * failures follow from that, and both were live on this machine (2026-08-24: a
9
+ * daemon started at 04:19 was still serving 9120 at 19:20, hours after the
10
+ * source it was built from had been replaced):
11
+ *
12
+ * - `daemon start` after an edit but before a build starts the PREVIOUS
13
+ * build, reports success, and nothing anywhere names the gap.
14
+ * - `daemon start` while a daemon is already up exits 0 with "already
15
+ * running" — correct when it is the same code, and a lie about what is
16
+ * serving the port when it is not. `dist/cli.js` is overwritten in place, so
17
+ * the running process keeps executing bytes that no longer exist on disk;
18
+ * no timestamp, pid or version string distinguishes the two.
19
+ *
20
+ * So the build gets an identity: a digest of the JavaScript the daemon would
21
+ * actually load. It is CONTENT-based rather than mtime-based on purpose —
22
+ * `tsc` rewrites every output on every run, so an mtime stamp would report a
23
+ * rebuild that changed nothing as a different build and restart a healthy
24
+ * daemon for it. The question being asked is "is the incumbent running the same
25
+ * code I would run?", and only content answers that.
26
+ *
27
+ * The daemon reports the identity it CAPTURED AT STARTUP (see the memo below),
28
+ * never one recomputed at request time: a daemon that recomputed would report
29
+ * the new build the moment someone rebuilt, i.e. it would report exactly the
30
+ * state this module exists to detect.
31
+ */
32
+ /** Workspace packages whose `dist` the daemon actually loads, in build order. */
33
+ export declare const DAEMON_BUILD_PACKAGES: readonly ["shared", "hooks", "bridge"];
34
+ export type DaemonBuildPackage = (typeof DAEMON_BUILD_PACKAGES)[number];
35
+ export interface DistBuildIdentity {
36
+ /** 12 hex chars, or null when no dist tree could be read at all. */
37
+ id: string | null;
38
+ /** The dist directories that went into it (realpaths, deduped). */
39
+ trees: string[];
40
+ files: number;
41
+ bytes: number;
42
+ }
43
+ /**
44
+ * The workspace root of a source checkout, or null when this is an installed
45
+ * package.
46
+ *
47
+ * Keyed on `pnpm-workspace.yaml` beside a `bridge/src`: an installed
48
+ * `@agentdeck/bridge` has a `dist` and no `src`, and nothing else on the path
49
+ * up from `bridge/dist` carries both markers.
50
+ */
51
+ export declare function findSourceCheckout(startDir?: string): string | null;
52
+ /**
53
+ * Digest the built JavaScript this process would load, reading the files now.
54
+ *
55
+ * The uncached entry point exists for exactly one caller: the CLI, comparing
56
+ * the tree before and after running the compiler. Everything else wants
57
+ * `distBuildIdentity()`.
58
+ */
59
+ export declare function computeDistBuildIdentity(): DistBuildIdentity;
60
+ /**
61
+ * The digest, memoized for the life of the process.
62
+ *
63
+ * The memo is the point rather than an optimisation: the daemon calls this once
64
+ * at startup and every later `/health` answers with that same value, so a
65
+ * rebuild underneath a running daemon shows up as a MISMATCH instead of being
66
+ * quietly absorbed. A CLI that has just rebuilt re-executes itself (a new
67
+ * process, a fresh memo) rather than continuing in place — mixing a freshly
68
+ * compiled `daemon-server.js` into a process that already loaded the old
69
+ * `cli.js` is not a build anyone chose.
70
+ */
71
+ export declare function distBuildIdentity(): DistBuildIdentity;
72
+ /** Convenience: just the digest. */
73
+ export declare function distBuildId(): string | null;
74
+ export interface StalePackage {
75
+ pkg: DaemonBuildPackage;
76
+ /** The newest source file that the build does not contain. */
77
+ newestSource: string;
78
+ sourceMtimeMs: number;
79
+ /** 0 when the package has no dist at all — it has never been built. */
80
+ distMtimeMs: number;
81
+ }
82
+ /**
83
+ * Packages whose `src` is newer than their `dist` — i.e. edits that no build
84
+ * has picked up yet.
85
+ *
86
+ * Compared PER PACKAGE, not against one global build time: the three are built
87
+ * by separate `tsc` invocations at separate moments, and a single newest-dist
88
+ * timestamp would call `shared` current whenever `bridge` had been rebuilt
89
+ * after it.
90
+ *
91
+ * Test sources are excluded deliberately — they compile to nothing the daemon
92
+ * loads, and counting them would report a stale build for every test edit and
93
+ * make the warning worth ignoring.
94
+ *
95
+ * Read this as a CONSERVATIVE pre-filter, not as proof: it is one-directional.
96
+ * "No source is newer than its build" is reliable (nothing writes a source file
97
+ * with a backdated mtime — git checkout stamps the current time), so a clean
98
+ * answer safely skips the compiler. The other direction over-reports, and must:
99
+ * `shared` is a composite project, so `tsc` keys on content hashes and rewrites
100
+ * NOTHING — not even its `.tsbuildinfo` — when a `touch`, a rebase or a
101
+ * worktree switch bumps an mtime without changing a byte. That is why the
102
+ * caller settles the question by running the compiler and comparing build
103
+ * digests rather than by trusting this.
104
+ */
105
+ export declare function findStaleSources(root: string): StalePackage[];
106
+ export interface BuildResult {
107
+ ok: boolean;
108
+ /** Why it could not run, when `ok` is false and no compiler ran at all. */
109
+ reason?: string;
110
+ }
111
+ /**
112
+ * Rebuild the stale packages, in dependency order.
113
+ *
114
+ * Only the stale ones: `bridge/dist` does not embed `shared`'s output (it
115
+ * imports it at runtime through the workspace symlink), so a `shared` edit does
116
+ * not invalidate a `bridge` build. Ordering still matters for the case where
117
+ * more than one is stale — `bridge`'s `tsc` reads `shared/dist/*.d.ts`.
118
+ *
119
+ * stdio is inherited: a build that fails must show the compiler's own errors,
120
+ * and a build that takes 30 seconds must show that it is running. Swallowing
121
+ * either would leave "start" looking hung or looking successful.
122
+ */
123
+ export declare function buildPackages(root: string, pkgs: readonly DaemonBuildPackage[], pnpmBin?: string): BuildResult;
124
+ //# sourceMappingURL=daemon-build-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-build-identity.d.ts","sourceRoot":"","sources":["../src/daemon-build-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAQH,iFAAiF;AACjF,eAAO,MAAM,qBAAqB,wCAAyC,CAAC;AAC5E,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,mEAAmE;IACnE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAyBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,SAAmB,GAAG,MAAM,GAAG,IAAI,CAS7E;AAiDD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,IAAI,iBAAiB,CAyB5D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,CAGrD;AAED,oCAAoC;AACpC,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAE3C;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,kBAAkB,CAAC;IACxB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;CACrB;AA8BD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAe7D;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,kBAAkB,EAAE,EAAE,OAAO,SAAS,GAAG,WAAW,CAgB9G"}
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Which build of AgentDeck is actually running, and whether it is the newest
3
+ * one on this disk.
4
+ *
5
+ * A dev checkout hands `agentdeck` to the shell as a shim that executes
6
+ * `bridge/dist/cli.js` in the repo, so "the version I am running" is whatever
7
+ * `tsc` last wrote there — a fact with no stamp on it anywhere. Two silent
8
+ * failures follow from that, and both were live on this machine (2026-08-24: a
9
+ * daemon started at 04:19 was still serving 9120 at 19:20, hours after the
10
+ * source it was built from had been replaced):
11
+ *
12
+ * - `daemon start` after an edit but before a build starts the PREVIOUS
13
+ * build, reports success, and nothing anywhere names the gap.
14
+ * - `daemon start` while a daemon is already up exits 0 with "already
15
+ * running" — correct when it is the same code, and a lie about what is
16
+ * serving the port when it is not. `dist/cli.js` is overwritten in place, so
17
+ * the running process keeps executing bytes that no longer exist on disk;
18
+ * no timestamp, pid or version string distinguishes the two.
19
+ *
20
+ * So the build gets an identity: a digest of the JavaScript the daemon would
21
+ * actually load. It is CONTENT-based rather than mtime-based on purpose —
22
+ * `tsc` rewrites every output on every run, so an mtime stamp would report a
23
+ * rebuild that changed nothing as a different build and restart a healthy
24
+ * daemon for it. The question being asked is "is the incumbent running the same
25
+ * code I would run?", and only content answers that.
26
+ *
27
+ * The daemon reports the identity it CAPTURED AT STARTUP (see the memo below),
28
+ * never one recomputed at request time: a daemon that recomputed would report
29
+ * the new build the moment someone rebuilt, i.e. it would report exactly the
30
+ * state this module exists to detect.
31
+ */
32
+ import { createHash } from 'crypto';
33
+ import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from 'fs';
34
+ import { spawnSync } from 'child_process';
35
+ import { dirname, join, relative, sep } from 'path';
36
+ import { fileURLToPath } from 'url';
37
+ /** Workspace packages whose `dist` the daemon actually loads, in build order. */
38
+ export const DAEMON_BUILD_PACKAGES = ['shared', 'hooks', 'bridge'];
39
+ /**
40
+ * `bridge/dist` — the directory this module was loaded from.
41
+ *
42
+ * With one deliberate exception: when this file is being executed straight from
43
+ * `bridge/src` (vitest, tsx), the built tree it should describe is the sibling
44
+ * `dist`. Reporting the source directory instead would digest a directory with
45
+ * no `.js` in it and answer "no build at all", which is a wrong answer rather
46
+ * than a missing one.
47
+ */
48
+ function selfDistDir() {
49
+ const here = dirname(fileURLToPath(import.meta.url));
50
+ if (here.split(sep).pop() === 'src') {
51
+ const sibling = join(dirname(here), 'dist');
52
+ if (existsSync(sibling))
53
+ return sibling;
54
+ }
55
+ return here;
56
+ }
57
+ /** `bridge/` — the package root of the running CLI. */
58
+ function selfPackageDir() {
59
+ return dirname(selfDistDir());
60
+ }
61
+ /**
62
+ * The workspace root of a source checkout, or null when this is an installed
63
+ * package.
64
+ *
65
+ * Keyed on `pnpm-workspace.yaml` beside a `bridge/src`: an installed
66
+ * `@agentdeck/bridge` has a `dist` and no `src`, and nothing else on the path
67
+ * up from `bridge/dist` carries both markers.
68
+ */
69
+ export function findSourceCheckout(startDir = selfPackageDir()) {
70
+ let dir = startDir;
71
+ for (let i = 0; i < 6; i++) {
72
+ if (existsSync(join(dir, 'pnpm-workspace.yaml')) && existsSync(join(dir, 'bridge', 'src')))
73
+ return dir;
74
+ const parent = dirname(dir);
75
+ if (parent === dir)
76
+ break;
77
+ dir = parent;
78
+ }
79
+ return null;
80
+ }
81
+ /**
82
+ * Every dist tree the daemon loads code from.
83
+ *
84
+ * `shared` and `hooks` are separate packages reached through node_modules
85
+ * symlinks, so hashing `bridge/dist` alone would call a daemon "current" while
86
+ * it ran a stale `shared`. Both layouts resolve here: the workspace sibling
87
+ * (`<root>/shared/dist`) and the installed copy
88
+ * (`bridge/node_modules/@agentdeck/shared/dist`). In a pnpm workspace the two
89
+ * are the same directory through a symlink, which `realpathSync` collapses.
90
+ */
91
+ function distTrees() {
92
+ const trees = [];
93
+ const add = (dir) => {
94
+ if (!existsSync(dir))
95
+ return;
96
+ let real = dir;
97
+ try {
98
+ real = realpathSync(dir);
99
+ }
100
+ catch { /* keep the literal path */ }
101
+ if (!trees.includes(real))
102
+ trees.push(real);
103
+ };
104
+ add(selfDistDir());
105
+ const root = findSourceCheckout();
106
+ for (const pkg of DAEMON_BUILD_PACKAGES) {
107
+ if (pkg === 'bridge')
108
+ continue;
109
+ if (root)
110
+ add(join(root, pkg, 'dist'));
111
+ add(join(selfPackageDir(), 'node_modules', '@agentdeck', pkg, 'dist'));
112
+ }
113
+ return trees.sort();
114
+ }
115
+ /** Every `.js` under `dir`, relative and sorted, skipping test output. */
116
+ function jsFilesUnder(dir) {
117
+ const out = [];
118
+ const walk = (current) => {
119
+ let entries;
120
+ try {
121
+ entries = readdirSync(current, { withFileTypes: true });
122
+ }
123
+ catch {
124
+ return;
125
+ }
126
+ for (const entry of entries) {
127
+ if (entry.name === 'node_modules' || entry.name === '__tests__')
128
+ continue;
129
+ const full = join(current, entry.name);
130
+ if (entry.isDirectory())
131
+ walk(full);
132
+ else if (entry.isFile() && (entry.name.endsWith('.js') || entry.name.endsWith('.cjs')))
133
+ out.push(full);
134
+ }
135
+ };
136
+ walk(dir);
137
+ return out.sort();
138
+ }
139
+ let memoized = null;
140
+ /**
141
+ * Digest the built JavaScript this process would load, reading the files now.
142
+ *
143
+ * The uncached entry point exists for exactly one caller: the CLI, comparing
144
+ * the tree before and after running the compiler. Everything else wants
145
+ * `distBuildIdentity()`.
146
+ */
147
+ export function computeDistBuildIdentity() {
148
+ const trees = distTrees();
149
+ const hash = createHash('sha256');
150
+ let files = 0;
151
+ let bytes = 0;
152
+ for (const tree of trees) {
153
+ // The tree's own basename, not its absolute path: two checkouts of the same
154
+ // commit must digest identically, or a worktree would always read as a
155
+ // different build from the repo it was cut from.
156
+ const label = tree.split(sep).slice(-2).join('/');
157
+ for (const file of jsFilesUnder(tree)) {
158
+ let content;
159
+ try {
160
+ content = readFileSync(file);
161
+ }
162
+ catch {
163
+ continue;
164
+ }
165
+ hash.update(`${label}/${relative(tree, file).split(sep).join('/')}\0${content.length}\0`);
166
+ hash.update(content);
167
+ files++;
168
+ bytes += content.length;
169
+ }
170
+ }
171
+ return {
172
+ id: files > 0 ? hash.digest('hex').slice(0, 12) : null,
173
+ trees,
174
+ files,
175
+ bytes,
176
+ };
177
+ }
178
+ /**
179
+ * The digest, memoized for the life of the process.
180
+ *
181
+ * The memo is the point rather than an optimisation: the daemon calls this once
182
+ * at startup and every later `/health` answers with that same value, so a
183
+ * rebuild underneath a running daemon shows up as a MISMATCH instead of being
184
+ * quietly absorbed. A CLI that has just rebuilt re-executes itself (a new
185
+ * process, a fresh memo) rather than continuing in place — mixing a freshly
186
+ * compiled `daemon-server.js` into a process that already loaded the old
187
+ * `cli.js` is not a build anyone chose.
188
+ */
189
+ export function distBuildIdentity() {
190
+ if (!memoized)
191
+ memoized = computeDistBuildIdentity();
192
+ return memoized;
193
+ }
194
+ /** Convenience: just the digest. */
195
+ export function distBuildId() {
196
+ return distBuildIdentity().id;
197
+ }
198
+ /** Newest mtime under `dir` among files `accept`s, with the file that set it. */
199
+ function newestFile(dir, accept) {
200
+ let best = null;
201
+ const walk = (current) => {
202
+ let entries;
203
+ try {
204
+ entries = readdirSync(current, { withFileTypes: true });
205
+ }
206
+ catch {
207
+ return;
208
+ }
209
+ for (const entry of entries) {
210
+ if (entry.name === 'node_modules' || entry.name === '__tests__' || entry.name.startsWith('.'))
211
+ continue;
212
+ const full = join(current, entry.name);
213
+ if (entry.isDirectory()) {
214
+ walk(full);
215
+ continue;
216
+ }
217
+ if (!entry.isFile() || !accept(entry.name))
218
+ continue;
219
+ let mtimeMs;
220
+ try {
221
+ mtimeMs = statSync(full).mtimeMs;
222
+ }
223
+ catch {
224
+ continue;
225
+ }
226
+ if (!best || mtimeMs > best.mtimeMs)
227
+ best = { path: full, mtimeMs };
228
+ }
229
+ };
230
+ walk(dir);
231
+ return best;
232
+ }
233
+ const isBuildableSource = (name) => name.endsWith('.ts')
234
+ && !name.endsWith('.d.ts')
235
+ && !name.endsWith('.test.ts')
236
+ && !name.endsWith('.spec.ts');
237
+ const isBuildOutput = (name) => name.endsWith('.js') || name.endsWith('.cjs');
238
+ /**
239
+ * Packages whose `src` is newer than their `dist` — i.e. edits that no build
240
+ * has picked up yet.
241
+ *
242
+ * Compared PER PACKAGE, not against one global build time: the three are built
243
+ * by separate `tsc` invocations at separate moments, and a single newest-dist
244
+ * timestamp would call `shared` current whenever `bridge` had been rebuilt
245
+ * after it.
246
+ *
247
+ * Test sources are excluded deliberately — they compile to nothing the daemon
248
+ * loads, and counting them would report a stale build for every test edit and
249
+ * make the warning worth ignoring.
250
+ *
251
+ * Read this as a CONSERVATIVE pre-filter, not as proof: it is one-directional.
252
+ * "No source is newer than its build" is reliable (nothing writes a source file
253
+ * with a backdated mtime — git checkout stamps the current time), so a clean
254
+ * answer safely skips the compiler. The other direction over-reports, and must:
255
+ * `shared` is a composite project, so `tsc` keys on content hashes and rewrites
256
+ * NOTHING — not even its `.tsbuildinfo` — when a `touch`, a rebase or a
257
+ * worktree switch bumps an mtime without changing a byte. That is why the
258
+ * caller settles the question by running the compiler and comparing build
259
+ * digests rather than by trusting this.
260
+ */
261
+ export function findStaleSources(root) {
262
+ const stale = [];
263
+ for (const pkg of DAEMON_BUILD_PACKAGES) {
264
+ const srcDir = join(root, pkg, 'src');
265
+ const distDir = join(root, pkg, 'dist');
266
+ if (!existsSync(srcDir))
267
+ continue;
268
+ const newestSrc = newestFile(srcDir, isBuildableSource);
269
+ if (!newestSrc)
270
+ continue;
271
+ const newestDist = existsSync(distDir) ? newestFile(distDir, isBuildOutput) : null;
272
+ const distMtimeMs = newestDist?.mtimeMs ?? 0;
273
+ if (newestSrc.mtimeMs > distMtimeMs) {
274
+ stale.push({ pkg, newestSource: newestSrc.path, sourceMtimeMs: newestSrc.mtimeMs, distMtimeMs });
275
+ }
276
+ }
277
+ return stale;
278
+ }
279
+ /**
280
+ * Rebuild the stale packages, in dependency order.
281
+ *
282
+ * Only the stale ones: `bridge/dist` does not embed `shared`'s output (it
283
+ * imports it at runtime through the workspace symlink), so a `shared` edit does
284
+ * not invalidate a `bridge` build. Ordering still matters for the case where
285
+ * more than one is stale — `bridge`'s `tsc` reads `shared/dist/*.d.ts`.
286
+ *
287
+ * stdio is inherited: a build that fails must show the compiler's own errors,
288
+ * and a build that takes 30 seconds must show that it is running. Swallowing
289
+ * either would leave "start" looking hung or looking successful.
290
+ */
291
+ export function buildPackages(root, pkgs, pnpmBin = 'pnpm') {
292
+ const ordered = DAEMON_BUILD_PACKAGES.filter((p) => pkgs.includes(p));
293
+ if (ordered.length === 0)
294
+ return { ok: true };
295
+ for (const pkg of ordered) {
296
+ const res = spawnSync(pnpmBin, ['--filter', `@agentdeck/${pkg}`, 'build'], {
297
+ cwd: root,
298
+ stdio: 'inherit',
299
+ shell: process.platform === 'win32',
300
+ });
301
+ if (res.error) {
302
+ const err = res.error;
303
+ return { ok: false, reason: err.code === 'ENOENT' ? `\`${pnpmBin}\` is not on PATH` : String(err.message) };
304
+ }
305
+ if (res.status !== 0)
306
+ return { ok: false };
307
+ }
308
+ return { ok: true };
309
+ }
310
+ //# sourceMappingURL=daemon-build-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-build-identity.js","sourceRoot":"","sources":["../src/daemon-build-identity.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,28 @@ import { BridgeCore } from './bridge-core.js';
15
15
  import { type DaemonPortSource } from './daemon-port.js';
16
16
  import { type UsageFetchResult } from './usage-api.js';
17
17
  import { FeedPullTracker } from './card-feed.js';
18
+ import { type SurfaceOtaIdentity } from './surface-protocol.js';
19
+ import { type NetworkInterfaceInfo } from 'os';
20
+ interface StagedFw {
21
+ firmwarePath: string;
22
+ md5: string;
23
+ size: number;
24
+ stagedAt: number;
25
+ /** Build identity embedded by CrossPoint/Pocket Daily, when discoverable. */
26
+ firmwareVersion?: string;
27
+ }
28
+ declare function pullOtaSegment(firmware: Buffer, requestedFrom: number, requestedLimit?: number): {
29
+ from: number;
30
+ body: Buffer;
31
+ };
32
+ /** Pick the host's Wi-Fi address only when it shares the device subnet. This
33
+ * avoids the measured Ethernet→AP return-path loss on dual-homed Macs without
34
+ * changing global routes or affecting non-OTA traffic. */
35
+ declare function preferredPullOtaIp(remoteAddress: string, localAddress: string, interfaces?: NodeJS.Dict<NetworkInterfaceInfo[]>): string | undefined;
36
+ /** Read the NUL-terminated build identity already present in Pocket images.
37
+ * This avoids inventing another manifest field and also repairs older persisted
38
+ * stages that predate firmwareVersion. */
39
+ declare function embeddedFirmwareVersion(firmware: Buffer): string | undefined;
18
40
  /** Resolve a stage target (canonical board, registry key, or IP) to the board
19
41
  * string the advert is keyed on.
20
42
  *
@@ -31,9 +53,9 @@ import { FeedPullTracker } from './card-feed.js';
31
53
  * staging exists. An unrecognized target is kept verbatim — staging for a
32
54
  * board this daemon has not met yet is legitimate. */
33
55
  declare function resolveStagedFwBoard(target: string): string;
34
- /** Stage a build for a board. Reads the file once to fingerprint it; the file
35
- * itself is re-read at device download time (a rebuild at the same path is
36
- * re-fingerprinted by re-staging).
56
+ /** Stage a build for a board. Reads the file once to fingerprint it. The Feed
57
+ * advert path re-fingerprints a rebuild at the same path before advertising,
58
+ * and the download path re-reads the bytes that are actually served.
37
59
  *
38
60
  * `pullSeen` reports whether this daemon has actually observed a feed pull
39
61
  * from the board, because "staged" proves neither transfer nor install and a
@@ -41,18 +63,20 @@ declare function resolveStagedFwBoard(target: string): string;
41
63
  * image; a board that holds a live WS never asks, so its stage sits forever
42
64
  * while the CLI says it is handled. It is daemon-lifetime state, so `false`
43
65
  * means "not seen since this daemon started" — not "cannot pull". */
44
- declare function stageEsp32Fw(target: string, firmwarePath: string): {
66
+ declare function stageEsp32Fw(target: string, firmwarePath: string, offeredIdentity?: SurfaceOtaIdentity): {
45
67
  board: string;
46
68
  bytes: number;
47
69
  md5: string;
48
70
  pullSeen: boolean;
71
+ productId?: string;
72
+ updateChannel?: string;
49
73
  };
50
74
  /** The staged advert for a feed response, re-validated against the file on
51
75
  * disk so a rebuilt-in-place binary never adverts a stale md5. */
52
- declare function stagedFwAdvert(board: string | undefined): {
76
+ declare function stagedFwAdvert(board: string | undefined, identity?: SurfaceOtaIdentity, clientVersion?: string): ({
53
77
  size: number;
54
78
  md5: string;
55
- } | undefined;
79
+ } & Partial<SurfaceOtaIdentity>) | undefined;
56
80
  /**
57
81
  * Single-path transport dedup. A physical ESP32 can be reachable over BOTH a
58
82
  * USB serial connection and a WiFi WebSocket at once (e.g. inkdeck/ttgo/tc001
@@ -93,7 +117,11 @@ export declare const __wifiOtaTestApi: {
93
117
  resolveStagedFwBoard: typeof resolveStagedFwBoard;
94
118
  stageEsp32Fw: typeof stageEsp32Fw;
95
119
  stagedFwAdvert: typeof stagedFwAdvert;
120
+ embeddedFirmwareVersion: typeof embeddedFirmwareVersion;
121
+ pullOtaSegment: typeof pullOtaSegment;
122
+ preferredPullOtaIp: typeof preferredPullOtaIp;
96
123
  feedPulls: FeedPullTracker;
124
+ getStagedFw: (identity: SurfaceOtaIdentity) => StagedFw | undefined;
97
125
  clearStagedFwForTest: () => void;
98
126
  };
99
127
  declare function performWifiEsp32Ota(core: BridgeCore, target: string, firmwarePath: string): Promise<Record<string, unknown>>;
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-server.d.ts","sourceRoot":"","sources":["../src/daemon-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon-server.d.ts","sourceRoot":"","sources":["../src/daemon-server.ts"],"names":[],"mappings":"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"}