uxnan-bridge 0.0.1-alpha.20260621

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 (255) hide show
  1. package/README.md +150 -0
  2. package/dist/src/account-status.d.ts +13 -0
  3. package/dist/src/account-status.js +78 -0
  4. package/dist/src/account-status.js.map +1 -0
  5. package/dist/src/adapters/base-adapter.d.ts +18 -0
  6. package/dist/src/adapters/base-adapter.js +15 -0
  7. package/dist/src/adapters/base-adapter.js.map +1 -0
  8. package/dist/src/adapters/claude-adapter.d.ts +102 -0
  9. package/dist/src/adapters/claude-adapter.js +486 -0
  10. package/dist/src/adapters/claude-adapter.js.map +1 -0
  11. package/dist/src/adapters/claude-tools.d.ts +25 -0
  12. package/dist/src/adapters/claude-tools.js +146 -0
  13. package/dist/src/adapters/claude-tools.js.map +1 -0
  14. package/dist/src/adapters/codex-adapter.d.ts +116 -0
  15. package/dist/src/adapters/codex-adapter.js +912 -0
  16. package/dist/src/adapters/codex-adapter.js.map +1 -0
  17. package/dist/src/adapters/codex-app-server.d.ts +74 -0
  18. package/dist/src/adapters/codex-app-server.js +225 -0
  19. package/dist/src/adapters/codex-app-server.js.map +1 -0
  20. package/dist/src/adapters/codex-approval.d.ts +88 -0
  21. package/dist/src/adapters/codex-approval.js +160 -0
  22. package/dist/src/adapters/codex-approval.js.map +1 -0
  23. package/dist/src/adapters/codex-tools.d.ts +18 -0
  24. package/dist/src/adapters/codex-tools.js +106 -0
  25. package/dist/src/adapters/codex-tools.js.map +1 -0
  26. package/dist/src/adapters/content-blocks.d.ts +68 -0
  27. package/dist/src/adapters/content-blocks.js +205 -0
  28. package/dist/src/adapters/content-blocks.js.map +1 -0
  29. package/dist/src/adapters/echo-agent-adapter.d.ts +23 -0
  30. package/dist/src/adapters/echo-agent-adapter.js +72 -0
  31. package/dist/src/adapters/echo-agent-adapter.js.map +1 -0
  32. package/dist/src/adapters/gemini-adapter.d.ts +87 -0
  33. package/dist/src/adapters/gemini-adapter.js +594 -0
  34. package/dist/src/adapters/gemini-adapter.js.map +1 -0
  35. package/dist/src/adapters/gemini-tools.d.ts +4 -0
  36. package/dist/src/adapters/gemini-tools.js +48 -0
  37. package/dist/src/adapters/gemini-tools.js.map +1 -0
  38. package/dist/src/adapters/opencode-adapter.d.ts +74 -0
  39. package/dist/src/adapters/opencode-adapter.js +418 -0
  40. package/dist/src/adapters/opencode-adapter.js.map +1 -0
  41. package/dist/src/adapters/opencode-tools.d.ts +2 -0
  42. package/dist/src/adapters/opencode-tools.js +41 -0
  43. package/dist/src/adapters/opencode-tools.js.map +1 -0
  44. package/dist/src/adapters/pi-adapter.d.ts +92 -0
  45. package/dist/src/adapters/pi-adapter.js +467 -0
  46. package/dist/src/adapters/pi-adapter.js.map +1 -0
  47. package/dist/src/adapters/pi-tools.d.ts +10 -0
  48. package/dist/src/adapters/pi-tools.js +72 -0
  49. package/dist/src/adapters/pi-tools.js.map +1 -0
  50. package/dist/src/adapters/process-agent-adapter.d.ts +24 -0
  51. package/dist/src/adapters/process-agent-adapter.js +111 -0
  52. package/dist/src/adapters/process-agent-adapter.js.map +1 -0
  53. package/dist/src/adapters/resolve-claude.d.ts +13 -0
  54. package/dist/src/adapters/resolve-claude.js +57 -0
  55. package/dist/src/adapters/resolve-claude.js.map +1 -0
  56. package/dist/src/adapters/resolve-codex.d.ts +13 -0
  57. package/dist/src/adapters/resolve-codex.js +48 -0
  58. package/dist/src/adapters/resolve-codex.js.map +1 -0
  59. package/dist/src/adapters/resolve-gemini.d.ts +13 -0
  60. package/dist/src/adapters/resolve-gemini.js +47 -0
  61. package/dist/src/adapters/resolve-gemini.js.map +1 -0
  62. package/dist/src/adapters/resolve-opencode.d.ts +11 -0
  63. package/dist/src/adapters/resolve-opencode.js +49 -0
  64. package/dist/src/adapters/resolve-opencode.js.map +1 -0
  65. package/dist/src/adapters/resolve-pi.d.ts +13 -0
  66. package/dist/src/adapters/resolve-pi.js +46 -0
  67. package/dist/src/adapters/resolve-pi.js.map +1 -0
  68. package/dist/src/adapters/run-options.d.ts +22 -0
  69. package/dist/src/adapters/run-options.js +48 -0
  70. package/dist/src/adapters/run-options.js.map +1 -0
  71. package/dist/src/adapters/spawn.d.ts +20 -0
  72. package/dist/src/adapters/spawn.js +16 -0
  73. package/dist/src/adapters/spawn.js.map +1 -0
  74. package/dist/src/agents/agent-manager.d.ts +98 -0
  75. package/dist/src/agents/agent-manager.js +433 -0
  76. package/dist/src/agents/agent-manager.js.map +1 -0
  77. package/dist/src/agents/attachments.d.ts +28 -0
  78. package/dist/src/agents/attachments.js +121 -0
  79. package/dist/src/agents/attachments.js.map +1 -0
  80. package/dist/src/bridge-context.d.ts +45 -0
  81. package/dist/src/bridge-context.js +2 -0
  82. package/dist/src/bridge-context.js.map +1 -0
  83. package/dist/src/bridge-status.d.ts +12 -0
  84. package/dist/src/bridge-status.js +17 -0
  85. package/dist/src/bridge-status.js.map +1 -0
  86. package/dist/src/bridge.d.ts +37 -0
  87. package/dist/src/bridge.js +446 -0
  88. package/dist/src/bridge.js.map +1 -0
  89. package/dist/src/cli.d.ts +2 -0
  90. package/dist/src/cli.js +194 -0
  91. package/dist/src/cli.js.map +1 -0
  92. package/dist/src/conversation/session-history.d.ts +27 -0
  93. package/dist/src/conversation/session-history.js +1082 -0
  94. package/dist/src/conversation/session-history.js.map +1 -0
  95. package/dist/src/conversation/thread-store.d.ts +74 -0
  96. package/dist/src/conversation/thread-store.js +366 -0
  97. package/dist/src/conversation/thread-store.js.map +1 -0
  98. package/dist/src/daemon-config.d.ts +123 -0
  99. package/dist/src/daemon-config.js +64 -0
  100. package/dist/src/daemon-config.js.map +1 -0
  101. package/dist/src/daemon-state.d.ts +27 -0
  102. package/dist/src/daemon-state.js +76 -0
  103. package/dist/src/daemon-state.js.map +1 -0
  104. package/dist/src/git/git-runner.d.ts +24 -0
  105. package/dist/src/git/git-runner.js +63 -0
  106. package/dist/src/git/git-runner.js.map +1 -0
  107. package/dist/src/git/git-service.d.ts +76 -0
  108. package/dist/src/git/git-service.js +435 -0
  109. package/dist/src/git/git-service.js.map +1 -0
  110. package/dist/src/handler-router.d.ts +34 -0
  111. package/dist/src/handler-router.js +67 -0
  112. package/dist/src/handler-router.js.map +1 -0
  113. package/dist/src/handlers/account-handler.d.ts +4 -0
  114. package/dist/src/handlers/account-handler.js +27 -0
  115. package/dist/src/handlers/account-handler.js.map +1 -0
  116. package/dist/src/handlers/agent-handler.d.ts +2 -0
  117. package/dist/src/handlers/agent-handler.js +8 -0
  118. package/dist/src/handlers/agent-handler.js.map +1 -0
  119. package/dist/src/handlers/bridge-control-handler.d.ts +2 -0
  120. package/dist/src/handlers/bridge-control-handler.js +64 -0
  121. package/dist/src/handlers/bridge-control-handler.js.map +1 -0
  122. package/dist/src/handlers/desktop-handler.d.ts +12 -0
  123. package/dist/src/handlers/desktop-handler.js +5 -0
  124. package/dist/src/handlers/desktop-handler.js.map +1 -0
  125. package/dist/src/handlers/git-handler.d.ts +2 -0
  126. package/dist/src/handlers/git-handler.js +82 -0
  127. package/dist/src/handlers/git-handler.js.map +1 -0
  128. package/dist/src/handlers/index.d.ts +8 -0
  129. package/dist/src/handlers/index.js +22 -0
  130. package/dist/src/handlers/index.js.map +1 -0
  131. package/dist/src/handlers/not-implemented.d.ts +10 -0
  132. package/dist/src/handlers/not-implemented.js +21 -0
  133. package/dist/src/handlers/not-implemented.js.map +1 -0
  134. package/dist/src/handlers/notifications-handler.d.ts +2 -0
  135. package/dist/src/handlers/notifications-handler.js +62 -0
  136. package/dist/src/handlers/notifications-handler.js.map +1 -0
  137. package/dist/src/handlers/params.d.ts +11 -0
  138. package/dist/src/handlers/params.js +72 -0
  139. package/dist/src/handlers/params.js.map +1 -0
  140. package/dist/src/handlers/project-handler.d.ts +2 -0
  141. package/dist/src/handlers/project-handler.js +6 -0
  142. package/dist/src/handlers/project-handler.js.map +1 -0
  143. package/dist/src/handlers/thread-context-handler.d.ts +2 -0
  144. package/dist/src/handlers/thread-context-handler.js +211 -0
  145. package/dist/src/handlers/thread-context-handler.js.map +1 -0
  146. package/dist/src/handlers/workspace-handler.d.ts +2 -0
  147. package/dist/src/handlers/workspace-handler.js +101 -0
  148. package/dist/src/handlers/workspace-handler.js.map +1 -0
  149. package/dist/src/hooks/claude-approval-hook.d.ts +7 -0
  150. package/dist/src/hooks/claude-approval-hook.js +95 -0
  151. package/dist/src/hooks/claude-approval-hook.js.map +1 -0
  152. package/dist/src/hooks/gemini-approval-hook.d.ts +7 -0
  153. package/dist/src/hooks/gemini-approval-hook.js +113 -0
  154. package/dist/src/hooks/gemini-approval-hook.js.map +1 -0
  155. package/dist/src/index.d.ts +62 -0
  156. package/dist/src/index.js +65 -0
  157. package/dist/src/index.js.map +1 -0
  158. package/dist/src/keyring-secret-store.d.ts +36 -0
  159. package/dist/src/keyring-secret-store.js +70 -0
  160. package/dist/src/keyring-secret-store.js.map +1 -0
  161. package/dist/src/lock-file.d.ts +18 -0
  162. package/dist/src/lock-file.js +60 -0
  163. package/dist/src/lock-file.js.map +1 -0
  164. package/dist/src/logger.d.ts +28 -0
  165. package/dist/src/logger.js +99 -0
  166. package/dist/src/logger.js.map +1 -0
  167. package/dist/src/pairing/pairing-code-service.d.ts +45 -0
  168. package/dist/src/pairing/pairing-code-service.js +183 -0
  169. package/dist/src/pairing/pairing-code-service.js.map +1 -0
  170. package/dist/src/projects/project-registry.d.ts +14 -0
  171. package/dist/src/projects/project-registry.js +60 -0
  172. package/dist/src/projects/project-registry.js.map +1 -0
  173. package/dist/src/push/push-sender.d.ts +21 -0
  174. package/dist/src/push/push-sender.js +96 -0
  175. package/dist/src/push/push-sender.js.map +1 -0
  176. package/dist/src/push/push-service.d.ts +122 -0
  177. package/dist/src/push/push-service.js +260 -0
  178. package/dist/src/push/push-service.js.map +1 -0
  179. package/dist/src/qr.d.ts +17 -0
  180. package/dist/src/qr.js +31 -0
  181. package/dist/src/qr.js.map +1 -0
  182. package/dist/src/secret-store.d.ts +23 -0
  183. package/dist/src/secret-store.js +27 -0
  184. package/dist/src/secret-store.js.map +1 -0
  185. package/dist/src/secure-device-state.d.ts +16 -0
  186. package/dist/src/secure-device-state.js +63 -0
  187. package/dist/src/secure-device-state.js.map +1 -0
  188. package/dist/src/service-installer.d.ts +57 -0
  189. package/dist/src/service-installer.js +254 -0
  190. package/dist/src/service-installer.js.map +1 -0
  191. package/dist/src/session-state.d.ts +14 -0
  192. package/dist/src/session-state.js +19 -0
  193. package/dist/src/session-state.js.map +1 -0
  194. package/dist/src/transport/crypto.d.ts +43 -0
  195. package/dist/src/transport/crypto.js +78 -0
  196. package/dist/src/transport/crypto.js.map +1 -0
  197. package/dist/src/transport/lan-server.d.ts +33 -0
  198. package/dist/src/transport/lan-server.js +105 -0
  199. package/dist/src/transport/lan-server.js.map +1 -0
  200. package/dist/src/transport/local-hosts.d.ts +17 -0
  201. package/dist/src/transport/local-hosts.js +30 -0
  202. package/dist/src/transport/local-hosts.js.map +1 -0
  203. package/dist/src/transport/mdns-advertiser.d.ts +83 -0
  204. package/dist/src/transport/mdns-advertiser.js +282 -0
  205. package/dist/src/transport/mdns-advertiser.js.map +1 -0
  206. package/dist/src/transport/message-io.d.ts +33 -0
  207. package/dist/src/transport/message-io.js +87 -0
  208. package/dist/src/transport/message-io.js.map +1 -0
  209. package/dist/src/transport/outbound-log.d.ts +24 -0
  210. package/dist/src/transport/outbound-log.js +78 -0
  211. package/dist/src/transport/outbound-log.js.map +1 -0
  212. package/dist/src/transport/relay-client.d.ts +19 -0
  213. package/dist/src/transport/relay-client.js +27 -0
  214. package/dist/src/transport/relay-client.js.map +1 -0
  215. package/dist/src/transport/secure-channel.d.ts +33 -0
  216. package/dist/src/transport/secure-channel.js +81 -0
  217. package/dist/src/transport/secure-channel.js.map +1 -0
  218. package/dist/src/transport/server-handshake.d.ts +49 -0
  219. package/dist/src/transport/server-handshake.js +137 -0
  220. package/dist/src/transport/server-handshake.js.map +1 -0
  221. package/dist/src/transport/session-handler.d.ts +19 -0
  222. package/dist/src/transport/session-handler.js +134 -0
  223. package/dist/src/transport/session-handler.js.map +1 -0
  224. package/dist/src/transport/session-registry.d.ts +58 -0
  225. package/dist/src/transport/session-registry.js +91 -0
  226. package/dist/src/transport/session-registry.js.map +1 -0
  227. package/dist/src/transport/trust-store.d.ts +23 -0
  228. package/dist/src/transport/trust-store.js +33 -0
  229. package/dist/src/transport/trust-store.js.map +1 -0
  230. package/dist/src/transport/ws-adapter.d.ts +7 -0
  231. package/dist/src/transport/ws-adapter.js +16 -0
  232. package/dist/src/transport/ws-adapter.js.map +1 -0
  233. package/dist/src/version.d.ts +1 -0
  234. package/dist/src/version.js +13 -0
  235. package/dist/src/version.js.map +1 -0
  236. package/dist/src/workspace/browse-service.d.ts +10 -0
  237. package/dist/src/workspace/browse-service.js +97 -0
  238. package/dist/src/workspace/browse-service.js.map +1 -0
  239. package/dist/src/workspace/checkpoint-service.d.ts +21 -0
  240. package/dist/src/workspace/checkpoint-service.js +219 -0
  241. package/dist/src/workspace/checkpoint-service.js.map +1 -0
  242. package/dist/src/workspace/path-guard.d.ts +7 -0
  243. package/dist/src/workspace/path-guard.js +51 -0
  244. package/dist/src/workspace/path-guard.js.map +1 -0
  245. package/dist/src/workspace/workspace-service.d.ts +8 -0
  246. package/dist/src/workspace/workspace-service.js +111 -0
  247. package/dist/src/workspace/workspace-service.js.map +1 -0
  248. package/package.json +46 -0
  249. package/scripts/extract-gemini-hook.mjs +16 -0
  250. package/scripts/fake-approval-bridge.mjs +23 -0
  251. package/scripts/install-service-linux.sh +38 -0
  252. package/scripts/install-service-macos.sh +38 -0
  253. package/scripts/install-service-windows.ps1 +26 -0
  254. package/scripts/test-gemini-hook-e2e.mjs +168 -0
  255. package/scripts/write-gemini-settings.mjs +31 -0
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Turn attachment delivery.
3
+ *
4
+ * The phone sends inline image attachments on `turn/send { attachments }`. No
5
+ * agent CLI accepts inline base64 over the headless stdio path, but every
6
+ * supported agent (Claude, Codex, OpenCode, pi, Gemini) can OPEN a local file
7
+ * with its own file/vision tools. So the bridge materializes each attachment to
8
+ * a file and references the path in the prompt — CLI-agnostic, no per-adapter
9
+ * image handling required.
10
+ *
11
+ * IMPORTANT: the file is written **inside the agent's working directory**
12
+ * (`<cwd>/.uxnan-attachments/<turnId>/`) and referenced by a **cwd-relative**
13
+ * path, because sandboxed agents confine file reads to the workspace (Gemini
14
+ * `--approval-mode`, Codex `workspace-write`, Claude `acceptEdits`) and reject a
15
+ * path outside it. The dir is cleaned up when the turn ends (see AgentManager).
16
+ *
17
+ * Source: architecture/02a-system-architecture.md §5.8 (agent turns) +
18
+ * uxnanmobile/FOR-DEV.md → Conversation / timeline → Attach.
19
+ */
20
+ import { mkdir, writeFile } from 'node:fs/promises';
21
+ import { tmpdir } from 'node:os';
22
+ import { join, relative, sep } from 'node:path';
23
+ /** Sub-directory (under the thread cwd) the bridge drops turn attachments into. */
24
+ export const ATTACHMENTS_DIRNAME = '.uxnan-attachments';
25
+ /** Extension for a known image MIME type (no leading dot). */
26
+ function extensionFor(mimeType) {
27
+ switch (mimeType.toLowerCase()) {
28
+ case 'image/png':
29
+ return 'png';
30
+ case 'image/jpeg':
31
+ case 'image/jpg':
32
+ return 'jpg';
33
+ case 'image/webp':
34
+ return 'webp';
35
+ case 'image/gif':
36
+ return 'gif';
37
+ case 'image/heic':
38
+ return 'heic';
39
+ case 'image/bmp':
40
+ return 'bmp';
41
+ default:
42
+ return 'bin';
43
+ }
44
+ }
45
+ /**
46
+ * Writes each inline attachment to a file under the thread's working directory
47
+ * and returns the absolute paths plus a ready-to-append prompt note (which
48
+ * references the files by a cwd-relative path). Tolerant: attachments without
49
+ * usable `base64Data` are skipped (an attachment that is only a workspace
50
+ * `path` is referenced by that path). Never throws on a single bad attachment.
51
+ */
52
+ export async function materializeAttachments(attachments, turnId, options = {}) {
53
+ if (attachments.length === 0)
54
+ return { paths: [], note: '' };
55
+ const cwd = options.cwd;
56
+ const baseDir = cwd ? join(cwd, ATTACHMENTS_DIRNAME) : join(tmpdir(), 'uxnan-attachments');
57
+ const dir = join(baseDir, sanitizeSegment(turnId));
58
+ const paths = [];
59
+ const refs = [];
60
+ let madeDir = false;
61
+ for (let i = 0; i < attachments.length; i += 1) {
62
+ const att = attachments[i];
63
+ if (!att)
64
+ continue;
65
+ // An attachment that is already an on-disk workspace file: reference it
66
+ // directly (no need to copy), the agent can open it in place.
67
+ if (!att.base64Data && att.path) {
68
+ paths.push(att.path);
69
+ refs.push(referencePath(att.path, cwd));
70
+ continue;
71
+ }
72
+ if (!att.base64Data)
73
+ continue;
74
+ let bytes;
75
+ try {
76
+ bytes = Buffer.from(att.base64Data, 'base64');
77
+ }
78
+ catch {
79
+ continue;
80
+ }
81
+ if (bytes.length === 0)
82
+ continue;
83
+ if (!madeDir) {
84
+ await mkdir(dir, { recursive: true });
85
+ madeDir = true;
86
+ }
87
+ const file = join(dir, `image-${i}.${extensionFor(att.mimeType ?? 'image/png')}`);
88
+ try {
89
+ await writeFile(file, bytes);
90
+ paths.push(file);
91
+ refs.push(referencePath(file, cwd));
92
+ }
93
+ catch {
94
+ // Best-effort: a single write failure must not abort the turn.
95
+ }
96
+ }
97
+ if (paths.length === 0)
98
+ return { paths: [], note: '' };
99
+ const label = paths.length > 1 ? 'images' : 'image';
100
+ const list = refs.map((p) => `- ${p}`).join('\n');
101
+ const note = `[Attached ${label} (open with your file/vision tools):\n${list}\n]`;
102
+ return { paths, ...(madeDir ? { dir } : {}), note };
103
+ }
104
+ /**
105
+ * Reference path used in the prompt: relative to `cwd` (POSIX separators) when
106
+ * the file lives inside it, otherwise the path as-is. Relative keeps the
107
+ * reference inside the agent's sandbox.
108
+ */
109
+ function referencePath(absPath, cwd) {
110
+ if (!cwd)
111
+ return absPath;
112
+ const rel = relative(cwd, absPath);
113
+ if (!rel || rel.startsWith('..'))
114
+ return absPath;
115
+ return rel.split(sep).join('/');
116
+ }
117
+ /** Strip path separators / unsafe chars from a path segment. */
118
+ function sanitizeSegment(value) {
119
+ return value.replace(/[^a-zA-Z0-9._-]/g, '_') || 'turn';
120
+ }
121
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../src/agents/attachments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Shared context passed to every JSON-RPC handler.
3
+ */
4
+ import type { DaemonConfig } from './daemon-config.js';
5
+ import type { DaemonState } from './daemon-state.js';
6
+ import type { SecureDeviceState } from './secure-device-state.js';
7
+ import type { SessionState } from './session-state.js';
8
+ import type { SessionRegistry } from './transport/session-registry.js';
9
+ import type { TrustStore } from './transport/trust-store.js';
10
+ import type { ThreadStore } from './conversation/thread-store.js';
11
+ import type { SessionHistoryReader } from './conversation/session-history.js';
12
+ import type { AgentManager } from './agents/agent-manager.js';
13
+ import type { ProjectRegistry } from './projects/project-registry.js';
14
+ import type { BrowseService } from './workspace/browse-service.js';
15
+ import type { PushService } from './push/push-service.js';
16
+ import type { Logger } from './logger.js';
17
+ export interface BridgeContext {
18
+ readonly version: string;
19
+ readonly startedAt: number;
20
+ readonly config: DaemonConfig;
21
+ readonly state: DaemonState;
22
+ readonly deviceState: SecureDeviceState;
23
+ readonly sessions: SessionState;
24
+ /** Live encrypted sinks for connected phones (bridge → phone notifications). */
25
+ readonly sessionRegistry: SessionRegistry;
26
+ /** Persisted trusted phones (Ed25519 identity + metadata, no secrets). */
27
+ readonly trustStore: TrustStore;
28
+ /** Persistent conversation store. */
29
+ readonly threadStore: ThreadStore;
30
+ /** Reads agent on-disk session logs as a `turn/list` fallback (§5.8.8). */
31
+ readonly sessionHistory: SessionHistoryReader;
32
+ /** Agent turn orchestration. */
33
+ readonly agentManager: AgentManager;
34
+ /** The project directories the phone may open. */
35
+ readonly projects: ProjectRegistry;
36
+ /** Root-confined directory browsing for plug-and-play project selection. */
37
+ readonly browse: BrowseService;
38
+ /** Push-notification coordination (token registration + turn-end delivery). */
39
+ readonly pushService: PushService;
40
+ readonly logger: Logger;
41
+ /** Whether at least one relay connection is currently serving a phone. */
42
+ relayConnected(): boolean;
43
+ /** Injected clock (epoch ms) for testability. */
44
+ now(): number;
45
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bridge-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-context.js","sourceRoot":"","sources":["../../src/bridge-context.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import type { BridgeStatus } from '@uxnan/shared';
2
+ export interface BridgeStatusInput {
3
+ version: string;
4
+ relayConnected: boolean;
5
+ lanEnabled: boolean;
6
+ activeSessions: number;
7
+ /** Process start time in epoch ms. */
8
+ startedAt: number;
9
+ /** Current time in epoch ms (injected for testability). */
10
+ now: number;
11
+ }
12
+ export declare function buildBridgeStatus(input: BridgeStatusInput): BridgeStatus;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Heartbeat / status snapshot of the bridge.
3
+ *
4
+ * Source: architecture/02a-system-architecture.md §5.8.2 (bridge-status).
5
+ */
6
+ import { platform } from 'node:os';
7
+ export function buildBridgeStatus(input) {
8
+ return {
9
+ version: input.version,
10
+ relayConnected: input.relayConnected,
11
+ lanEnabled: input.lanEnabled,
12
+ activeSessions: input.activeSessions,
13
+ platform: platform(),
14
+ uptimeMs: Math.max(0, input.now - input.startedAt),
15
+ };
16
+ }
17
+ //# sourceMappingURL=bridge-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-status.js","sourceRoot":"","sources":["../../src/bridge-status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAcnC,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,QAAQ,EAAE,QAAQ,EAAE;QACpB,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC;KACnD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { type BridgeStatus, type PairingPayload } from '@uxnan/shared';
2
+ import type { BridgeContext } from './bridge-context.js';
3
+ import { HandlerRouter } from './handler-router.js';
4
+ import type { SecretStore } from './secret-store.js';
5
+ import { type LogLevel } from './logger.js';
6
+ import { type TrustStore } from './transport/trust-store.js';
7
+ export interface StartBridgeOptions {
8
+ /** Override the daemon state directory (defaults to `~/.uxnan`). */
9
+ baseDir?: string;
10
+ /** Inject a secret store (defaults to an in-memory one). */
11
+ secretStore?: SecretStore;
12
+ logLevel?: LogLevel;
13
+ /** Inject a clock (epoch ms) for testability. */
14
+ now?: () => number;
15
+ }
16
+ export interface Bridge {
17
+ readonly context: BridgeContext;
18
+ readonly router: HandlerRouter;
19
+ readonly trustStore: TrustStore;
20
+ status(): BridgeStatus;
21
+ generatePairingQr(): PairingPayload;
22
+ /** The current manual-pairing code to show on the PC (rotates on expiry). */
23
+ currentPairingCode(): string;
24
+ /** Connect to the relay as `mac` and serve a phone for the given session. */
25
+ connectRelay(sessionId: string): Promise<void>;
26
+ /** Start the direct-LAN WebSocket server; resolves with the bound port. */
27
+ startLan(): Promise<{
28
+ port: number;
29
+ }>;
30
+ /**
31
+ * Push a JSON-RPC notification to a connected phone. Returns `true` if it was
32
+ * sent live, `false` if the device is offline and it was buffered.
33
+ */
34
+ notify(deviceId: string, method: string, params?: unknown): boolean;
35
+ stop(): Promise<void>;
36
+ }
37
+ export declare function startBridge(options?: StartBridgeOptions): Promise<Bridge>;