@agentdeck/bridge 1.0.23 → 1.1.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.
- package/dist/adapters/openclaw.d.ts +74 -4
- package/dist/adapters/openclaw.d.ts.map +1 -1
- package/dist/adapters/openclaw.js +235 -43
- package/dist/adapters/openclaw.js.map +1 -1
- package/dist/apme/adapters/openclaw-hook.d.ts +38 -10
- package/dist/apme/adapters/openclaw-hook.d.ts.map +1 -1
- package/dist/apme/adapters/openclaw-hook.js +181 -37
- package/dist/apme/adapters/openclaw-hook.js.map +1 -1
- package/dist/apme/collector.d.ts +37 -1
- package/dist/apme/collector.d.ts.map +1 -1
- package/dist/apme/collector.js +277 -35
- package/dist/apme/collector.js.map +1 -1
- package/dist/apme/pareto.d.ts +2 -1
- package/dist/apme/pareto.d.ts.map +1 -1
- package/dist/apme/pareto.js +15 -4
- package/dist/apme/pareto.js.map +1 -1
- package/dist/apme/recommend.d.ts +24 -1
- package/dist/apme/recommend.d.ts.map +1 -1
- package/dist/apme/recommend.js +43 -7
- package/dist/apme/recommend.js.map +1 -1
- package/dist/apme/store.d.ts +6 -0
- package/dist/apme/store.d.ts.map +1 -1
- package/dist/apme/store.js +244 -72
- package/dist/apme/store.js.map +1 -1
- package/dist/bridge-core.d.ts +10 -1
- package/dist/bridge-core.d.ts.map +1 -1
- package/dist/bridge-core.js +20 -5
- package/dist/bridge-core.js.map +1 -1
- package/dist/card-feed.d.ts +46 -1
- package/dist/card-feed.d.ts.map +1 -1
- package/dist/card-feed.js +166 -6
- package/dist/card-feed.js.map +1 -1
- package/dist/cli.d.ts +45 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +388 -27
- package/dist/cli.js.map +1 -1
- package/dist/daemon-build-identity.d.ts +124 -0
- package/dist/daemon-build-identity.d.ts.map +1 -0
- package/dist/daemon-build-identity.js +310 -0
- package/dist/daemon-build-identity.js.map +1 -0
- package/dist/daemon-server.d.ts +34 -6
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +613 -108
- package/dist/daemon-server.js.map +1 -1
- package/dist/daemon-takeover.d.ts +11 -0
- package/dist/daemon-takeover.d.ts.map +1 -1
- package/dist/daemon-takeover.js +62 -17
- package/dist/daemon-takeover.js.map +1 -1
- package/dist/daemon.js +1 -1
- package/dist/daemon.js.map +1 -1
- package/dist/esp32-flash.d.ts.map +1 -1
- package/dist/esp32-flash.js +19 -3
- package/dist/esp32-flash.js.map +1 -1
- package/dist/esp32-serial.d.ts +14 -0
- package/dist/esp32-serial.d.ts.map +1 -1
- package/dist/esp32-serial.js +19 -1
- package/dist/esp32-serial.js.map +1 -1
- package/dist/glance-frame.d.ts.map +1 -1
- package/dist/glance-frame.js +3 -1
- package/dist/glance-frame.js.map +1 -1
- package/dist/hook-codex-sessions.d.ts +3 -1
- package/dist/hook-codex-sessions.d.ts.map +1 -1
- package/dist/hook-codex-sessions.js +27 -7
- package/dist/hook-codex-sessions.js.map +1 -1
- package/dist/legacy-rearm-ledger.d.ts +56 -0
- package/dist/legacy-rearm-ledger.d.ts.map +1 -0
- package/dist/legacy-rearm-ledger.js +66 -0
- package/dist/legacy-rearm-ledger.js.map +1 -0
- package/dist/mdns.d.ts +33 -0
- package/dist/mdns.d.ts.map +1 -1
- package/dist/mdns.js +91 -2
- package/dist/mdns.js.map +1 -1
- package/dist/openclaw-session.d.ts.map +1 -1
- package/dist/openclaw-session.js +13 -0
- package/dist/openclaw-session.js.map +1 -1
- package/dist/openclaw-timeline-feed.d.ts +84 -0
- package/dist/openclaw-timeline-feed.d.ts.map +1 -0
- package/dist/openclaw-timeline-feed.js +162 -0
- package/dist/openclaw-timeline-feed.js.map +1 -0
- package/dist/openclaw-transcript-timeline.d.ts +103 -0
- package/dist/openclaw-transcript-timeline.d.ts.map +1 -0
- package/dist/openclaw-transcript-timeline.js +328 -0
- package/dist/openclaw-transcript-timeline.js.map +1 -0
- package/dist/passive-observer.d.ts +21 -1
- package/dist/passive-observer.d.ts.map +1 -1
- package/dist/passive-observer.js +37 -3
- package/dist/passive-observer.js.map +1 -1
- package/dist/relayed-usage.d.ts +68 -0
- package/dist/relayed-usage.d.ts.map +1 -0
- package/dist/relayed-usage.js +80 -0
- package/dist/relayed-usage.js.map +1 -0
- package/dist/session-aggregator.d.ts +3 -0
- package/dist/session-aggregator.d.ts.map +1 -1
- package/dist/session-aggregator.js.map +1 -1
- package/dist/session-registry.d.ts +1 -0
- package/dist/session-registry.d.ts.map +1 -1
- package/dist/surface-protocol.d.ts +84 -0
- package/dist/surface-protocol.d.ts.map +1 -0
- package/dist/surface-protocol.js +235 -0
- package/dist/surface-protocol.js.map +1 -0
- package/dist/timeline-store.d.ts +1 -1
- package/dist/timeline-store.d.ts.map +1 -1
- package/dist/timeline-store.js +16 -1
- package/dist/timeline-store.js.map +1 -1
- package/dist/tui/renderer.d.ts.map +1 -1
- package/dist/tui/renderer.js +35 -0
- package/dist/tui/renderer.js.map +1 -1
- package/dist/weather-config.d.ts +17 -0
- package/dist/weather-config.d.ts.map +1 -0
- package/dist/weather-config.js +54 -0
- package/dist/weather-config.js.map +1 -0
- package/dist/weather.d.ts +44 -4
- package/dist/weather.d.ts.map +1 -1
- package/dist/weather.js +223 -15
- package/dist/weather.js.map +1 -1
- package/dist/ws-server.d.ts.map +1 -1
- package/dist/ws-server.js +55 -5
- package/dist/ws-server.js.map +1 -1
- package/fm-helper/AgentDeckFMHelper.swift +51 -5
- package/package.json +3 -3
|
@@ -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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"}
|
package/dist/daemon-server.d.ts
CHANGED
|
@@ -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
|
|
35
|
-
*
|
|
36
|
-
* re-
|
|
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":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,SAAS,MAAM,IAAI,CAAC;AAC3B,OAAO,EAAE,UAAU,EAA8B,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"daemon-server.d.ts","sourceRoot":"","sources":["../src/daemon-server.ts"],"names":[],"mappings":"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"}
|