super-dsh 0.1.6 → 0.1.10-e

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 (260) hide show
  1. package/README.md +25 -3
  2. package/agent-agy/cordis.patch.yml +7 -4
  3. package/agent-agy/dist/agent.d.ts +12 -11
  4. package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
  5. package/agent-agy/dist/agy-auth-gateway.js +233 -0
  6. package/agent-agy/dist/agy-auth.d.ts +153 -0
  7. package/agent-agy/dist/agy-auth.js +179 -0
  8. package/agent-agy/dist/agy-cli-client.d.ts +39 -9
  9. package/agent-agy/dist/agy-cli-client.js +82 -18
  10. package/agent-agy/dist/agy-store.d.ts +8 -0
  11. package/agent-agy/dist/index.d.ts +46 -16
  12. package/agent-agy/dist/index.js +82 -56
  13. package/agent-agy/dist/models.d.ts +70 -0
  14. package/agent-agy/dist/models.js +102 -3
  15. package/agent-agy/package.json +7 -5
  16. package/agent-agy-sdk/cordis.patch.yml +58 -0
  17. package/agent-agy-sdk/dist/adapter.d.ts +15 -0
  18. package/agent-agy-sdk/dist/adapter.js +42 -0
  19. package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
  20. package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
  21. package/agent-agy-sdk/dist/agent.d.ts +138 -0
  22. package/agent-agy-sdk/dist/agent.js +494 -0
  23. package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
  24. package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
  25. package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
  26. package/agent-agy-sdk/dist/agy-sessions.js +107 -0
  27. package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
  28. package/agent-agy-sdk/dist/agy-store.js +83 -0
  29. package/agent-agy-sdk/dist/inbox.d.ts +26 -0
  30. package/agent-agy-sdk/dist/inbox.js +53 -0
  31. package/agent-agy-sdk/dist/index.d.ts +93 -0
  32. package/agent-agy-sdk/dist/index.js +476 -0
  33. package/agent-agy-sdk/dist/models.d.ts +41 -0
  34. package/agent-agy-sdk/dist/models.js +74 -0
  35. package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
  36. package/agent-agy-sdk/dist/sdk-venv.js +173 -0
  37. package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
  38. package/agent-agy-sdk/dist/world-plugin.js +82 -0
  39. package/agent-agy-sdk/package.json +64 -0
  40. package/agent-claude/dist/adapter.js +106 -31
  41. package/agent-claude/dist/agent.js +154 -17
  42. package/agent-claude/dist/claude-client.js +84 -43
  43. package/agent-claude/dist/claude-launch.js +101 -0
  44. package/agent-claude/dist/claude-native-config.js +169 -0
  45. package/agent-claude/dist/claude-provider-gateway.js +340 -0
  46. package/agent-claude/dist/claude-providers.js +391 -0
  47. package/agent-claude/dist/claude-route.js +152 -0
  48. package/agent-claude/dist/index.js +214 -37
  49. package/agent-claude/dist/models.js +14 -0
  50. package/agent-claude/dist/sdk-runtime.js +320 -0
  51. package/agent-claude/package.json +6 -4
  52. package/agent-codex/README.md +141 -36
  53. package/agent-codex/cordis.patch.yml +14 -10
  54. package/agent-codex/dist/adapter.js +64 -28
  55. package/agent-codex/dist/agent.js +255 -81
  56. package/agent-codex/dist/app-server-approvals.js +165 -0
  57. package/agent-codex/dist/app-server-client.js +723 -0
  58. package/agent-codex/dist/app-server-events.js +432 -0
  59. package/agent-codex/dist/app-server-protocol.js +95 -0
  60. package/agent-codex/dist/app-server-wire.js +299 -0
  61. package/agent-codex/dist/codex-launch.js +78 -0
  62. package/agent-codex/dist/codex-native-config.js +392 -0
  63. package/agent-codex/dist/codex-provider-gateway.js +402 -0
  64. package/agent-codex/dist/codex-providers.js +376 -0
  65. package/agent-codex/dist/codex-route.js +86 -0
  66. package/agent-codex/dist/index.js +256 -115
  67. package/agent-codex/dist/permission.js +75 -1
  68. package/agent-codex/package.json +1 -2
  69. package/agent-codex-sdk/README.md +79 -0
  70. package/agent-codex-sdk/cordis.patch.yml +81 -0
  71. package/agent-codex-sdk/dist/adapter.js +91 -0
  72. package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
  73. package/agent-codex-sdk/dist/agent.js +1085 -0
  74. package/agent-codex-sdk/dist/codex-native-config.js +392 -0
  75. package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
  76. package/agent-codex-sdk/dist/codex-providers.js +376 -0
  77. package/agent-codex-sdk/dist/codex-route.js +86 -0
  78. package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
  79. package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
  80. package/agent-codex-sdk/dist/codex-store.js +180 -0
  81. package/agent-codex-sdk/dist/inbox.js +53 -0
  82. package/agent-codex-sdk/dist/index.js +739 -0
  83. package/agent-codex-sdk/dist/permission.js +71 -0
  84. package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
  85. package/agent-codex-sdk/dist/session-map.js +167 -0
  86. package/agent-codex-sdk/dist/world-plugin.js +93 -0
  87. package/agent-codex-sdk/package.json +79 -0
  88. package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
  89. package/agent-omp/README.md +72 -55
  90. package/agent-omp/dist/agent.js +36 -11
  91. package/agent-omp/dist/index.js +92 -52
  92. package/agent-omp/dist/lazy-rpc.js +11 -4
  93. package/agent-omp/dist/omp-cli.js +114 -97
  94. package/agent-omp/dist/omp-store.js +12 -4
  95. package/agent-omp/dist/permission.js +70 -5
  96. package/agent-omp/dist/rpc-client.js +409 -0
  97. package/agent-omp/dist/world-plugin.js +36 -3
  98. package/agent-omp/package.json +2 -6
  99. package/agent-omp-sdk/README.md +103 -0
  100. package/agent-omp-sdk/cordis.patch.yml +108 -0
  101. package/agent-omp-sdk/dist/adapter.d.ts +21 -0
  102. package/agent-omp-sdk/dist/adapter.js +36 -0
  103. package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
  104. package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
  105. package/agent-omp-sdk/dist/agent.d.ts +64 -0
  106. package/agent-omp-sdk/dist/agent.js +1178 -0
  107. package/agent-omp-sdk/dist/discovery.d.ts +57 -0
  108. package/agent-omp-sdk/dist/discovery.js +116 -0
  109. package/agent-omp-sdk/dist/inbox.d.ts +28 -0
  110. package/agent-omp-sdk/dist/inbox.js +53 -0
  111. package/agent-omp-sdk/dist/index.d.ts +60 -0
  112. package/agent-omp-sdk/dist/index.js +632 -0
  113. package/agent-omp-sdk/dist/knobs.d.ts +34 -0
  114. package/agent-omp-sdk/dist/knobs.js +50 -0
  115. package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
  116. package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
  117. package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
  118. package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
  119. package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
  120. package/agent-omp-sdk/dist/mobile-boot.js +38 -0
  121. package/agent-omp-sdk/dist/models.d.ts +39 -0
  122. package/agent-omp-sdk/dist/models.js +299 -0
  123. package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
  124. package/agent-omp-sdk/dist/omp-cli.js +164 -0
  125. package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
  126. package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
  127. package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
  128. package/agent-omp-sdk/dist/omp-executable.js +30 -0
  129. package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
  130. package/agent-omp-sdk/dist/omp-store.js +526 -0
  131. package/agent-omp-sdk/dist/pairing.d.ts +7 -0
  132. package/agent-omp-sdk/dist/pairing.js +45 -0
  133. package/agent-omp-sdk/dist/permission.d.ts +138 -0
  134. package/agent-omp-sdk/dist/permission.js +161 -0
  135. package/agent-omp-sdk/dist/protocol.d.ts +189 -0
  136. package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
  137. package/agent-omp-sdk/dist/rpc-types.js +1 -0
  138. package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
  139. package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
  140. package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
  141. package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
  142. package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
  143. package/agent-omp-sdk/dist/sidecar-client.js +197 -0
  144. package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
  145. package/agent-omp-sdk/dist/store/adapter.js +47 -0
  146. package/agent-omp-sdk/dist/store/db.d.ts +70 -0
  147. package/agent-omp-sdk/dist/store/db.js +210 -0
  148. package/agent-omp-sdk/dist/store/index.d.ts +23 -0
  149. package/agent-omp-sdk/dist/store/index.js +59 -0
  150. package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
  151. package/agent-omp-sdk/dist/store/reconcile.js +51 -0
  152. package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
  153. package/agent-omp-sdk/dist/store/schema.js +40 -0
  154. package/agent-omp-sdk/dist/transport.d.ts +49 -0
  155. package/agent-omp-sdk/dist/transport.js +35 -0
  156. package/agent-omp-sdk/dist/world-home.d.ts +4 -0
  157. package/agent-omp-sdk/dist/world-home.js +23 -0
  158. package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
  159. package/agent-omp-sdk/dist/world-plugin.js +137 -0
  160. package/agent-omp-sdk/package.json +87 -0
  161. package/client/index.js +1883 -287
  162. package/cordis.patch.yml +80 -0
  163. package/package.json +23 -9
  164. package/superd-hub/dist/a2a-delivery.d.ts +189 -0
  165. package/superd-hub/dist/a2a-delivery.js +240 -0
  166. package/superd-hub/dist/a2a-host.d.ts +76 -0
  167. package/superd-hub/dist/a2a-host.js +145 -0
  168. package/superd-hub/dist/a2a-ingest.d.ts +31 -0
  169. package/superd-hub/dist/a2a-ingest.js +636 -0
  170. package/superd-hub/dist/a2a-log.d.ts +17 -0
  171. package/superd-hub/dist/a2a-log.js +42 -0
  172. package/superd-hub/dist/a2a-row.d.ts +65 -0
  173. package/superd-hub/dist/a2a-row.js +162 -0
  174. package/superd-hub/dist/a2a-service.d.ts +357 -0
  175. package/superd-hub/dist/a2a-service.js +980 -0
  176. package/superd-hub/dist/a2a-wire.d.ts +220 -0
  177. package/superd-hub/dist/a2a-wire.js +305 -0
  178. package/superd-hub/dist/agent-ids.d.ts +10 -0
  179. package/superd-hub/dist/agent-ids.js +68 -0
  180. package/superd-hub/dist/agent-roster.d.ts +29 -18
  181. package/superd-hub/dist/agent-roster.js +54 -15
  182. package/superd-hub/dist/agent-status.d.ts +119 -0
  183. package/superd-hub/dist/agent-status.js +386 -0
  184. package/superd-hub/dist/client/agent-settings.d.ts +210 -0
  185. package/superd-hub/dist/client/agent-settings.js +300 -0
  186. package/superd-hub/dist/client/mesh-api.d.ts +134 -0
  187. package/superd-hub/dist/client/mesh-api.js +219 -0
  188. package/superd-hub/dist/client/mesh-groups.d.ts +63 -0
  189. package/superd-hub/dist/client/mesh-groups.js +66 -0
  190. package/superd-hub/dist/client/roster.d.ts +48 -0
  191. package/superd-hub/dist/client/roster.js +102 -0
  192. package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
  193. package/superd-hub/dist/client/runtime-settings-api.js +137 -0
  194. package/superd-hub/dist/client/switch.d.ts +165 -0
  195. package/superd-hub/dist/client/switch.js +295 -0
  196. package/superd-hub/dist/exec-pty-channel.d.ts +58 -0
  197. package/superd-hub/dist/exec-pty-channel.js +162 -0
  198. package/superd-hub/dist/exec-pty-framing.d.ts +32 -0
  199. package/superd-hub/dist/exec-pty-framing.js +81 -0
  200. package/superd-hub/dist/exec-pty-rpc.d.ts +21 -0
  201. package/superd-hub/dist/exec-pty-rpc.js +128 -0
  202. package/superd-hub/dist/exec-pty-session.d.ts +76 -0
  203. package/superd-hub/dist/exec-pty-session.js +234 -0
  204. package/superd-hub/dist/exec.d.ts +56 -0
  205. package/superd-hub/dist/exec.js +225 -0
  206. package/superd-hub/dist/gateway.d.ts +39 -2
  207. package/superd-hub/dist/gateway.js +62 -3
  208. package/superd-hub/dist/hub-tool.d.ts +174 -0
  209. package/superd-hub/dist/hub-tool.js +464 -0
  210. package/superd-hub/dist/index.d.ts +15 -1
  211. package/superd-hub/dist/index.js +16 -0
  212. package/superd-hub/dist/machines.d.ts +45 -0
  213. package/superd-hub/dist/machines.js +125 -0
  214. package/superd-hub/dist/mesh-federate.d.ts +138 -0
  215. package/superd-hub/dist/mesh-federate.js +223 -0
  216. package/superd-hub/dist/mesh-gateway.d.ts +67 -0
  217. package/superd-hub/dist/mesh-gateway.js +408 -0
  218. package/superd-hub/dist/mesh-link.d.ts +274 -0
  219. package/superd-hub/dist/mesh-link.js +441 -0
  220. package/superd-hub/dist/mesh-rpc.d.ts +123 -0
  221. package/superd-hub/dist/mesh-rpc.js +250 -0
  222. package/superd-hub/dist/mux-client.d.ts +71 -0
  223. package/superd-hub/dist/mux-client.js +281 -0
  224. package/superd-hub/dist/pack-version.d.ts +2 -0
  225. package/superd-hub/dist/pack-version.js +30 -0
  226. package/superd-hub/dist/roster.d.ts +6 -0
  227. package/superd-hub/dist/rpc.d.ts +18 -2
  228. package/superd-hub/dist/rpc.js +34 -4
  229. package/superd-hub/dist/spawn-world.js +3 -1
  230. package/superd-hub/dist/switch-core.d.ts +62 -25
  231. package/superd-hub/dist/switch-core.js +53 -30
  232. package/superd-hub/dist/system-head.d.ts +22 -12
  233. package/superd-hub/dist/system-head.js +100 -84
  234. package/superd-hub/dist/wire-endpoints.d.ts +264 -0
  235. package/superd-hub/dist/wire-endpoints.js +180 -0
  236. package/superd-hub/lib/client/index.js +1883 -287
  237. package/superd-hub/package.json +11 -2
  238. package/agent-agy/dist/agent-preset-projection.d.ts +0 -31
  239. package/agent-agy/dist/agent-preset-projection.js +0 -33
  240. package/agent-claude/dist/agent-preset-projection.js +0 -30
  241. package/agent-codex/dist/agent-preset-projection.js +0 -37
  242. package/agent-codex/dist/app-home.js +0 -65
  243. package/agent-codex/dist/models.js +0 -152
  244. package/agent-codex/dist/spike.js +0 -46
  245. package/agent-hermes/dist/agent-preset-projection.js +0 -34
  246. package/agent-omp/dist/agent-preset-projection.js +0 -36
  247. package/agent-omp/dist/app-home.js +0 -86
  248. package/agent-omp/dist/sidecar-client.js +0 -195
  249. package/agent-pi/dist/agent-preset-projection.js +0 -29
  250. package/superd-hub/dist/client-shim.d.ts +0 -28
  251. package/superd-hub/dist/client-shim.js +0 -251
  252. package/superd-hub/dist/index-pass.d.ts +0 -22
  253. package/superd-hub/dist/index-pass.js +0 -47
  254. package/superd-hub/dist/labels.d.ts +0 -45
  255. package/superd-hub/dist/labels.js +0 -83
  256. /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
  257. /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
  258. /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
  259. /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
  260. /package/{agent-omp → agent-omp-sdk}/sidecar/main.ts +0 -0
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Runtime settings panels for the Hub's Agent Runtimes rows (P3, 2026-10-02
3
+ * user ruling).
4
+ *
5
+ * Interaction contract the UI follows (ruling, verbatim intent):
6
+ * - clicking the ROW BODY expands that runtime's OWN settings inline
7
+ * (accordion: at most one row open at a time);
8
+ * - the row's existing right-hand `switch` affordance is the ONLY switch —
9
+ * the panel never carries a second one.
10
+ *
11
+ * Config belongs to the adapter (agent-adapter-dev-rules §12), so this module
12
+ * owns only the presentation-side logic: which runtimes have a panel, the
13
+ * accordion transition, and a defensive parse of whatever the adapter's
14
+ * `*Auth/get` RPC returns. The adapter decides which auth methods exist, which
15
+ * are available on this machine, and which one is in force.
16
+ *
17
+ * Node-safe by construction (no DOM, no React, no fetch) — the host tsconfig
18
+ * dual-emits this file to `dist/client/agent-settings.js` so
19
+ * test/client-agent-settings.test.mjs can pin the parse and accordion rules
20
+ * under `node --test` (the roster.ts / mesh-api.ts precedent).
21
+ *
22
+ * @module superd-hub/client/agent-settings
23
+ */
24
+ /** One selectable auth method as the adapter describes it. */
25
+ export interface AuthMethodOption {
26
+ /** Stable id the RPC round-trips (`apiKey` | `oauth` | `adc`). */
27
+ readonly key: string;
28
+ /** Human label rendered on the option. */
29
+ readonly label: string;
30
+ /** Detected on THIS machine. Drives the availability annotation. */
31
+ readonly available: boolean;
32
+ /**
33
+ * Rendered but not selectable this round (the OAuth placeholder): the UI
34
+ * shows the shape and says why it is inert, instead of hiding it.
35
+ */
36
+ readonly placeholder: boolean;
37
+ /** One short line explaining the option (or why it is inert). */
38
+ readonly hint: string;
39
+ }
40
+ /** The adapter's answer to `<runtime>Auth/get`. */
41
+ export interface RuntimeAuthView {
42
+ readonly methods: readonly AuthMethodOption[];
43
+ /** The user's explicit persisted choice; `null` when they have not made one. */
44
+ readonly selected: string | null;
45
+ /** What a new session would ACTUALLY use right now (ladder fallback applied). */
46
+ readonly effective: string | null;
47
+ /** Native file the adapter maintains for this runtime, when it owns one. */
48
+ readonly settingsPath?: string;
49
+ /** Free-form note from the adapter (e.g. why a mode is unavailable). */
50
+ readonly note?: string;
51
+ }
52
+ /**
53
+ * A runtime's settings panel: which adapter Remote answers for it.
54
+ *
55
+ * The namespace is the adapter's own service key — the hub forwards
56
+ * `envelope.method` verbatim, so the client needs only the name. A runtime absent
57
+ * from this table has no panel yet: its row still expands, to an explicit empty
58
+ * state rather than a dead control (the interaction stays uniform, and a runtime
59
+ * with nothing to configure SAYS so).
60
+ */
61
+ export interface SettingsPanelSpec {
62
+ /** The adapter's Remote namespace (`agyAuth`). */
63
+ readonly namespace: string;
64
+ /**
65
+ * Which body the expanded row mounts. A runtime's config is not always a
66
+ * choice among a fixed set: Antigravity picks one sign-in form from a ladder,
67
+ * while Codex carries a LIST of providers the user adds, edits and removes
68
+ * (2026-10-03 ruling; the former active/select toggle is gone — which provider
69
+ * a Codex session runs on is DSH's own per-session model selection, not a
70
+ * hub-side switch). One namespace, two shapes — the kind discriminates.
71
+ */
72
+ readonly kind: 'auth' | 'providers';
73
+ }
74
+ /** The panel spec for a runtime, or `undefined` when it has none yet. */
75
+ export declare function settingsPanelFor(agentKey: string): SettingsPanelSpec | undefined;
76
+ /** Whether this runtime's row body expands into a real settings panel. */
77
+ export declare function hasSettingsPanel(agentKey: string): boolean;
78
+ /**
79
+ * Accordion transition: at most one row open. Clicking the open row closes it;
80
+ * clicking another moves the panel there in one click.
81
+ */
82
+ export declare function toggleExpanded(current: string | null, key: string): string | null;
83
+ /**
84
+ * Defensive parse of the RPC answer. Returns `undefined` for anything that is
85
+ * not a usable view (no methods, wrong shape, adapter absent) so the panel can
86
+ * render an explicit failure instead of an empty list that looks like success.
87
+ */
88
+ export declare function parseAuthView(raw: unknown): RuntimeAuthView | undefined;
89
+ /**
90
+ * The option the panel marks as in force: the effective one when the adapter
91
+ * named it, else the explicit selection. `undefined` when neither is known —
92
+ * the panel then marks nothing rather than guessing.
93
+ */
94
+ export declare function activeMethod(view: RuntimeAuthView): AuthMethodOption | undefined;
95
+ /** Whether an option may be picked (placeholders are rendered, never selected). */
96
+ export declare function selectable(option: AuthMethodOption): boolean;
97
+ /** One model behind a provider, as the panel lists it. */
98
+ export interface ProviderModelOption {
99
+ readonly id: string;
100
+ /** Human label; the adapter sends one, else the id stands in. */
101
+ readonly label: string;
102
+ readonly contextWindow?: number;
103
+ }
104
+ /**
105
+ * The auth shapes the provider faces use between them: `apiKey` is shared,
106
+ * codex adds `env` (the key lives in a named variable), claude adds
107
+ * `authToken` (a Bearer token). Each face's adapter rejects the other's
108
+ * addition on save, which is why the form offers kinds per view
109
+ * (`authKindOptions`) instead of one fixed list.
110
+ */
111
+ export type ProviderAuthKind = 'apiKey' | 'env' | 'authToken';
112
+ /** One configured provider, listed but never carrying its key. */
113
+ export interface ProviderOption {
114
+ readonly id: string;
115
+ readonly label: string;
116
+ readonly baseUrl: string;
117
+ readonly protocol: string;
118
+ readonly models: readonly ProviderModelOption[];
119
+ /** Which key shape the entry stores — see `ProviderAuthKind`. */
120
+ readonly authKind: ProviderAuthKind;
121
+ /** The variable an env-shaped provider expects. */
122
+ readonly envName?: string;
123
+ /** Whether a key is available — the ONLY thing the wire says about it. */
124
+ readonly hasKey: boolean;
125
+ }
126
+ /** One wire protocol the adapter offers, and whether it may be picked. */
127
+ export interface ProviderProtocolOption {
128
+ readonly value: string;
129
+ readonly label: string;
130
+ readonly available: boolean;
131
+ readonly hint: string;
132
+ }
133
+ /**
134
+ * The files this surface reads and writes, shown so where an edit lands is
135
+ * never a surprise. Only `store` is common: each face names its own native
136
+ * files (codex: config/auth/catalogs; claude: settings), and a face that
137
+ * lacks a slot simply omits it — the footer renders what is there.
138
+ */
139
+ export interface ProviderPaths {
140
+ readonly store: string;
141
+ readonly config?: string;
142
+ readonly auth?: string;
143
+ readonly catalogs?: string;
144
+ readonly settings?: string;
145
+ }
146
+ /** The adapter's answer to `codexProviders/get` / `claudeProviders/get` (and to every mutation). */
147
+ export interface RuntimeProvidersView {
148
+ readonly providers: readonly ProviderOption[];
149
+ /**
150
+ * What the user's OWN native config currently names (codex: the provider
151
+ * `~/.codex/config.toml` selects; claude: the endpoint the `settings.json`
152
+ * env pins). Informational only — there is no action attached to it, and
153
+ * DSH's per-session model selection (not this list) decides what a session
154
+ * runs.
155
+ */
156
+ readonly native: {
157
+ readonly providerId?: string;
158
+ readonly baseUrl?: string;
159
+ readonly model?: string;
160
+ } | null;
161
+ /**
162
+ * The wire protocols the adapter offers, in the order it offers them. Empty
163
+ * for a face with no protocol choice (claude) — the panel then omits the
164
+ * dropdown instead of inventing options the runtime cannot run.
165
+ */
166
+ readonly protocols: readonly ProviderProtocolOption[];
167
+ readonly paths: ProviderPaths;
168
+ /** Epoch ms of the last reconcile against the native config, when one has happened. */
169
+ readonly syncedAt?: number;
170
+ readonly note?: string;
171
+ }
172
+ /**
173
+ * Defensive parse of the adapter's providers answer.
174
+ *
175
+ * `undefined` for anything that is not a usable view — but an empty `providers`
176
+ * array is valid (a fresh install), and so is a provider whose `models` array
177
+ * is empty. `protocols` is the codex face's field: an ABSENT field (the claude
178
+ * face) reads as "no protocol choice" and never fails the parse, while a
179
+ * present-but-unusable list is a malformed codex answer and rejects as before.
180
+ */
181
+ export declare function parseProvidersView(raw: unknown): RuntimeProvidersView | undefined;
182
+ /** One selectable auth shape for the add/edit form (`authKindOptions`). */
183
+ export interface ProviderAuthKindOption {
184
+ readonly value: ProviderAuthKind;
185
+ readonly label: string;
186
+ readonly hint: string;
187
+ }
188
+ /**
189
+ * The auth shapes the add/edit form may pick for a provider, in display order.
190
+ *
191
+ * The view carries no explicit vocabulary field, so the panel reads it off the
192
+ * one field that distinguishes the faces today: `protocols`. The codex face
193
+ * advertises wire protocols and offers key-or-env-var; the claude face carries
194
+ * neither and offers its two header shapes instead. The list is per-view,
195
+ * never a fixed union — each adapter rejects the other's kinds on save, so a
196
+ * union dropdown would miscode silently. A third face extends the table.
197
+ */
198
+ export declare function authKindOptions(view: RuntimeProvidersView): readonly ProviderAuthKindOption[];
199
+ /**
200
+ * `provider / model` (codex) or `endpoint / model` (claude) — whichever halves
201
+ * the user's own native config names, joined for the one-line fact the panel
202
+ * states and never acts on.
203
+ */
204
+ export declare function nativeDescription(native: RuntimeProvidersView['native']): string;
205
+ /**
206
+ * The non-store paths joined for the panel's second footer line, in a fixed
207
+ * slot order. `undefined` when the face named none — the line is omitted
208
+ * entirely rather than rendered with blank slots.
209
+ */
210
+ export declare function nativePathsLine(paths: ProviderPaths): string | undefined;
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Runtime settings panels for the Hub's Agent Runtimes rows (P3, 2026-10-02
3
+ * user ruling).
4
+ *
5
+ * Interaction contract the UI follows (ruling, verbatim intent):
6
+ * - clicking the ROW BODY expands that runtime's OWN settings inline
7
+ * (accordion: at most one row open at a time);
8
+ * - the row's existing right-hand `switch` affordance is the ONLY switch —
9
+ * the panel never carries a second one.
10
+ *
11
+ * Config belongs to the adapter (agent-adapter-dev-rules §12), so this module
12
+ * owns only the presentation-side logic: which runtimes have a panel, the
13
+ * accordion transition, and a defensive parse of whatever the adapter's
14
+ * `*Auth/get` RPC returns. The adapter decides which auth methods exist, which
15
+ * are available on this machine, and which one is in force.
16
+ *
17
+ * Node-safe by construction (no DOM, no React, no fetch) — the host tsconfig
18
+ * dual-emits this file to `dist/client/agent-settings.js` so
19
+ * test/client-agent-settings.test.mjs can pin the parse and accordion rules
20
+ * under `node --test` (the roster.ts / mesh-api.ts precedent).
21
+ *
22
+ * @module superd-hub/client/agent-settings
23
+ */
24
+ const SETTINGS_PANELS = {
25
+ // The one runtime with a settings surface this round: the CLI adapter owns the
26
+ // auth ladder and is the configuration surface for the user's local Antigravity.
27
+ agy: { namespace: 'agyAuth', kind: 'auth' },
28
+ // Codex's own config.toml names exactly one `model_provider`, but that file
29
+ // is the USER's and no longer the hub's toggle: Super D hosts the list
30
+ // cc-switch otherwise holds (add / edit / remove) and the adapter owns both
31
+ // the list and whatever it does with the native file.
32
+ codex: { namespace: 'codexProviders', kind: 'providers' },
33
+ // Both Codex lines host the SAME provider list (2026-10-04): the SDK half is
34
+ // the same agent through a different transport, so it carries the same panel
35
+ // and the same Remote namespace. The two worlds keep separate stores under
36
+ // their own `agents/<key>/`, so neither sees the other's list.
37
+ 'codex-sdk': { namespace: 'codexProviders', kind: 'providers' },
38
+ // Claude serves the same providers view shape as Codex with no protocol
39
+ // dropdown: its adapter's view carries no `protocols` field (claude has no
40
+ // wire-protocol choice to make), so the body degrades to what the view does
41
+ // carry — two header auth kinds and its own native fact (2026-10-04).
42
+ claude: { namespace: 'claudeProviders', kind: 'providers' },
43
+ };
44
+ /** The panel spec for a runtime, or `undefined` when it has none yet. */
45
+ export function settingsPanelFor(agentKey) {
46
+ return SETTINGS_PANELS[agentKey];
47
+ }
48
+ /** Whether this runtime's row body expands into a real settings panel. */
49
+ export function hasSettingsPanel(agentKey) {
50
+ return settingsPanelFor(agentKey) !== undefined;
51
+ }
52
+ /**
53
+ * Accordion transition: at most one row open. Clicking the open row closes it;
54
+ * clicking another moves the panel there in one click.
55
+ */
56
+ export function toggleExpanded(current, key) {
57
+ return current === key ? null : key;
58
+ }
59
+ function str(value) {
60
+ return typeof value === 'string' && value !== '' ? value : undefined;
61
+ }
62
+ function methodOption(raw) {
63
+ if (typeof raw !== 'object' || raw === null)
64
+ return undefined;
65
+ const record = raw;
66
+ const key = str(record.key);
67
+ const label = str(record.label);
68
+ if (key === undefined || label === undefined)
69
+ return undefined;
70
+ return {
71
+ key,
72
+ label,
73
+ // Absent flags read as the conservative value: an older adapter that omits
74
+ // `available` must not render an option as usable when we cannot tell.
75
+ available: record.available === true,
76
+ placeholder: record.placeholder === true,
77
+ hint: str(record.hint) ?? '',
78
+ };
79
+ }
80
+ /**
81
+ * Defensive parse of the RPC answer. Returns `undefined` for anything that is
82
+ * not a usable view (no methods, wrong shape, adapter absent) so the panel can
83
+ * render an explicit failure instead of an empty list that looks like success.
84
+ */
85
+ export function parseAuthView(raw) {
86
+ if (typeof raw !== 'object' || raw === null)
87
+ return undefined;
88
+ const record = raw;
89
+ if (!Array.isArray(record.methods))
90
+ return undefined;
91
+ const methods = record.methods.map(methodOption).filter((m) => m !== undefined);
92
+ if (methods.length === 0)
93
+ return undefined;
94
+ const settingsPath = str(record.settingsPath);
95
+ const note = str(record.note);
96
+ return {
97
+ methods,
98
+ selected: str(record.selected) ?? null,
99
+ effective: str(record.effective) ?? null,
100
+ ...(settingsPath === undefined ? {} : { settingsPath }),
101
+ ...(note === undefined ? {} : { note }),
102
+ };
103
+ }
104
+ /**
105
+ * The option the panel marks as in force: the effective one when the adapter
106
+ * named it, else the explicit selection. `undefined` when neither is known —
107
+ * the panel then marks nothing rather than guessing.
108
+ */
109
+ export function activeMethod(view) {
110
+ const wanted = view.effective ?? view.selected;
111
+ if (wanted === null)
112
+ return undefined;
113
+ return view.methods.find((method) => method.key === wanted);
114
+ }
115
+ /** Whether an option may be picked (placeholders are rendered, never selected). */
116
+ export function selectable(option) {
117
+ return !option.placeholder;
118
+ }
119
+ function nonEmpty(value) {
120
+ return typeof value === 'string' && value !== '' ? value : undefined;
121
+ }
122
+ function modelOption(raw) {
123
+ if (typeof raw !== 'object' || raw === null)
124
+ return undefined;
125
+ const record = raw;
126
+ const id = nonEmpty(record.id);
127
+ if (id === undefined)
128
+ return undefined;
129
+ const contextWindow = record.contextWindow;
130
+ return {
131
+ id,
132
+ label: nonEmpty(record.displayName) ?? id,
133
+ ...(typeof contextWindow === 'number' && Number.isSafeInteger(contextWindow) && contextWindow > 0
134
+ ? { contextWindow }
135
+ : {}),
136
+ };
137
+ }
138
+ function providerAuthKind(raw) {
139
+ // An unstated or unknown kind reads as the shared conservative default,
140
+ // never as the other face's shape.
141
+ return raw === 'env' ? 'env' : raw === 'authToken' ? 'authToken' : 'apiKey';
142
+ }
143
+ function providerOption(raw) {
144
+ if (typeof raw !== 'object' || raw === null)
145
+ return undefined;
146
+ const record = raw;
147
+ const id = nonEmpty(record.id);
148
+ const label = nonEmpty(record.label);
149
+ const baseUrl = nonEmpty(record.baseUrl);
150
+ if (id === undefined || label === undefined || baseUrl === undefined)
151
+ return undefined;
152
+ const models = Array.isArray(record.models)
153
+ ? record.models.map(modelOption).filter((entry) => entry !== undefined)
154
+ : [];
155
+ const envName = nonEmpty(record.envName);
156
+ return {
157
+ id,
158
+ label,
159
+ baseUrl,
160
+ // An unknown protocol is never echoed into a control; the only value this
161
+ // harness can actually run is the safe default.
162
+ protocol: record.protocol === 'chat' ? 'chat' : 'responses',
163
+ models,
164
+ authKind: providerAuthKind(record.authKind),
165
+ ...(envName === undefined ? {} : { envName }),
166
+ hasKey: record.hasKey === true,
167
+ };
168
+ }
169
+ function protocolOption(raw) {
170
+ if (typeof raw !== 'object' || raw === null)
171
+ return undefined;
172
+ const record = raw;
173
+ const value = nonEmpty(record.value);
174
+ const label = nonEmpty(record.label);
175
+ if (value === undefined || label === undefined)
176
+ return undefined;
177
+ return { value, label, available: record.available === true, hint: nonEmpty(record.hint) ?? '' };
178
+ }
179
+ function providerPaths(raw) {
180
+ if (typeof raw !== 'object' || raw === null)
181
+ return undefined;
182
+ const record = raw;
183
+ const store = nonEmpty(record.store);
184
+ // The store is the only slot every face promises; the native files are the
185
+ // face's own, and an absent one stays absent rather than blank.
186
+ if (store === undefined)
187
+ return undefined;
188
+ const config = nonEmpty(record.config);
189
+ const auth = nonEmpty(record.auth);
190
+ const catalogs = nonEmpty(record.catalogs);
191
+ const settings = nonEmpty(record.settings);
192
+ return {
193
+ store,
194
+ ...(config === undefined ? {} : { config }),
195
+ ...(auth === undefined ? {} : { auth }),
196
+ ...(catalogs === undefined ? {} : { catalogs }),
197
+ ...(settings === undefined ? {} : { settings }),
198
+ };
199
+ }
200
+ /**
201
+ * Defensive parse of the adapter's providers answer.
202
+ *
203
+ * `undefined` for anything that is not a usable view — but an empty `providers`
204
+ * array is valid (a fresh install), and so is a provider whose `models` array
205
+ * is empty. `protocols` is the codex face's field: an ABSENT field (the claude
206
+ * face) reads as "no protocol choice" and never fails the parse, while a
207
+ * present-but-unusable list is a malformed codex answer and rejects as before.
208
+ */
209
+ export function parseProvidersView(raw) {
210
+ if (typeof raw !== 'object' || raw === null)
211
+ return undefined;
212
+ const record = raw;
213
+ if (!Array.isArray(record.providers))
214
+ return undefined;
215
+ // Absent `protocols` (the claude face) → nothing to offer, the panel omits
216
+ // the dropdown. Present (the codex face) → must parse to at least one
217
+ // option, exactly as before.
218
+ let protocols = [];
219
+ if (record.protocols !== undefined) {
220
+ if (!Array.isArray(record.protocols))
221
+ return undefined;
222
+ protocols = record.protocols.map(protocolOption).filter((entry) => entry !== undefined);
223
+ if (protocols.length === 0)
224
+ return undefined;
225
+ }
226
+ const paths = providerPaths(record.paths);
227
+ if (paths === undefined)
228
+ return undefined;
229
+ const providers = record.providers.map(providerOption).filter((entry) => entry !== undefined);
230
+ const syncedAt = record.syncedAt;
231
+ const note = nonEmpty(record.note);
232
+ return {
233
+ providers,
234
+ native: nativeConfig(record.native),
235
+ protocols,
236
+ paths,
237
+ ...(typeof syncedAt === 'number' && Number.isFinite(syncedAt) ? { syncedAt } : {}),
238
+ ...(note === undefined ? {} : { note }),
239
+ };
240
+ }
241
+ /**
242
+ * The user's own native config as the adapter last read it. `null` when the
243
+ * adapter said nothing; otherwise an object carrying whichever halves were
244
+ * named — codex names a provider id, claude an endpoint URL — and an empty
245
+ * one is still news (the panel says the file names nothing).
246
+ */
247
+ function nativeConfig(raw) {
248
+ if (typeof raw !== 'object' || raw === null)
249
+ return null;
250
+ const record = raw;
251
+ const providerId = nonEmpty(record.providerId);
252
+ const baseUrl = nonEmpty(record.baseUrl);
253
+ const model = nonEmpty(record.model);
254
+ return {
255
+ ...(providerId === undefined ? {} : { providerId }),
256
+ ...(baseUrl === undefined ? {} : { baseUrl }),
257
+ ...(model === undefined ? {} : { model }),
258
+ };
259
+ }
260
+ /** The codex face: a stored key, or the name of a variable holding it. */
261
+ const KEY_OR_ENV = [
262
+ { value: 'apiKey', label: 'API key', hint: 'Stored with the provider; injected at launch.' },
263
+ { value: 'env', label: 'Environment variable', hint: 'The child reads the key from a named variable.' },
264
+ ];
265
+ /** The claude face: both kinds are literal keys, differing only in the header. */
266
+ const TWO_HEADER_SHAPES = [
267
+ { value: 'apiKey', label: 'API key (x-api-key)', hint: 'Sent as the x-api-key header.' },
268
+ { value: 'authToken', label: 'Bearer token', hint: 'Sent as the Authorization header.' },
269
+ ];
270
+ /**
271
+ * The auth shapes the add/edit form may pick for a provider, in display order.
272
+ *
273
+ * The view carries no explicit vocabulary field, so the panel reads it off the
274
+ * one field that distinguishes the faces today: `protocols`. The codex face
275
+ * advertises wire protocols and offers key-or-env-var; the claude face carries
276
+ * neither and offers its two header shapes instead. The list is per-view,
277
+ * never a fixed union — each adapter rejects the other's kinds on save, so a
278
+ * union dropdown would miscode silently. A third face extends the table.
279
+ */
280
+ export function authKindOptions(view) {
281
+ return view.protocols.length > 0 ? KEY_OR_ENV : TWO_HEADER_SHAPES;
282
+ }
283
+ /**
284
+ * `provider / model` (codex) or `endpoint / model` (claude) — whichever halves
285
+ * the user's own native config names, joined for the one-line fact the panel
286
+ * states and never acts on.
287
+ */
288
+ export function nativeDescription(native) {
289
+ const parts = [native?.providerId ?? native?.baseUrl, native?.model].filter((part) => part !== undefined);
290
+ return parts.length === 0 ? 'no provider' : parts.join(' / ');
291
+ }
292
+ /**
293
+ * The non-store paths joined for the panel's second footer line, in a fixed
294
+ * slot order. `undefined` when the face named none — the line is omitted
295
+ * entirely rather than rendered with blank slots.
296
+ */
297
+ export function nativePathsLine(paths) {
298
+ const parts = [paths.config, paths.auth, paths.catalogs, paths.settings].filter((part) => part !== undefined);
299
+ return parts.length === 0 ? undefined : parts.join(' · ');
300
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Machine-mesh data access for the Hub machines panel (mesh P1, Task 5):
3
+ * the client half of `/api/superd/machines` (host side: mesh-rpc.ts) —
4
+ * same-origin fetch behind the standard browser-trust + cookie fence, the
5
+ * roster face's house style (`credentials: 'same-origin'`). The localStorage
6
+ * ledger era (machines-store.ts, retired with this module) ended: the hub's
7
+ * registry is the single source of truth, this file only fetches it and
8
+ * coerces the wire answer into row views.
9
+ *
10
+ * Node-safe by construction — no DOM, no react, no @deepseek-ai imports —
11
+ * so the host tsc emits it to `dist/client/mesh-api.js` and
12
+ * test/client-mesh-view.test.mjs runs the pure halves (coercion, token-URL
13
+ * pre-check) under `node --test` without jsdom: the switch-core/toast-core
14
+ * precedent in reverse (pure logic kept beside the fetch wrappers, all under
15
+ * src/client). No fetch happens at import time.
16
+ *
17
+ * @module superd-hub/client/mesh-api
18
+ */
19
+ /** Machine health as the hub reports it (mesh-rpc joins `'pending'` when the mesh-link status table has no entry for the row). */
20
+ export type MeshMachineStatus = 'pending' | 'reachable' | 'unreachable' | 'auth-expired';
21
+ /**
22
+ * One machine row for the panel: the wire's public projection (never token,
23
+ * never cookie) with `self` DERIVED from the response's self block — never
24
+ * stored per-row (the server's machines array carries remotes only; the
25
+ * flag exists so a self row surfacing in it still renders as self). Since
26
+ * I2 (mesh P3 5a) a reachable row may also carry `versionWarning` — the
27
+ * host's version-mismatch computation, coerced additively (absent stays
28
+ * absent; a non-string is dropped).
29
+ */
30
+ export interface MeshMachineView {
31
+ readonly id: string;
32
+ readonly name: string;
33
+ readonly label: string;
34
+ readonly origin: string;
35
+ readonly status: MeshMachineStatus;
36
+ readonly lastProbeAt?: number;
37
+ /** I2: present exactly when the hub's probe found the peer's superd
38
+ * version incompatible with ours (diff major/minor, or unparsable). */
39
+ readonly versionWarning?: string;
40
+ readonly self: boolean;
41
+ }
42
+ /** The response's self block: this machine's minted m4 id + label. */
43
+ export interface MeshSelfView {
44
+ readonly id: string;
45
+ readonly label: string;
46
+ }
47
+ /** The coerced GET answer: self (when the wire carried a usable one) + the remote rows. */
48
+ export interface MeshList {
49
+ readonly self?: MeshSelfView;
50
+ readonly machines: readonly MeshMachineView[];
51
+ }
52
+ /** The pairing input — origin is parsed out of the token URL SERVER-side (mesh-link), never a separate field. */
53
+ export interface AddMachineInput {
54
+ readonly name: string;
55
+ readonly label?: string;
56
+ readonly tokenUrl: string;
57
+ }
58
+ /**
59
+ * Coerce a raw GET body into the panel's view list. Any bad shape degrades
60
+ * to the empty list (rows dropped individually, self dropped as a block) —
61
+ * the UI never crashes on a malformed answer.
62
+ *
63
+ * @param raw - the parsed JSON body (or anything else the wire produced).
64
+ * @returns self (when usable) + the coerced remote rows.
65
+ */
66
+ export declare function coerceMachineList(raw: unknown): MeshList;
67
+ /**
68
+ * The version-warning chip for one machine row (I2): present EXACTLY when the
69
+ * coerced row carries a `versionWarning` — the Hub machines panel renders
70
+ * the chip iff this returns a value. Kept here beside the coercion so the
71
+ * presence contract stays unit-testable without jsdom (the HubPage seat is
72
+ * a one-line consumer following the existing chip patterns).
73
+ */
74
+ export declare function machineVersionChip(machine: Pick<MeshMachineView, 'versionWarning'>): {
75
+ text: string;
76
+ } | undefined;
77
+ /**
78
+ * GET the machine list (self + remotes).
79
+ *
80
+ * @returns the coerced list — a malformed body degrades to the empty list, never a throw.
81
+ * @throws when the request fails or the face answers non-2xx.
82
+ */
83
+ export declare function fetchMachines(): Promise<MeshList>;
84
+ /**
85
+ * POST a pairing `{name, label?, tokenUrl}` (label omitted → the server
86
+ * collapses it to the name).
87
+ *
88
+ * @throws Error(body.error) when the face answers non-2xx — the message is
89
+ * mesh-link's own, already token-redacted.
90
+ */
91
+ export declare function addMachine(input: AddMachineInput): Promise<void>;
92
+ /**
93
+ * DELETE one remote row by id (`{removed: boolean}` answers even for
94
+ * unknown ids — a false removal is a reload, not an error).
95
+ *
96
+ * @throws Error(body.error) on a non-2xx answer.
97
+ */
98
+ export declare function removeMachine(id: string): Promise<void>;
99
+ /**
100
+ * POST `{op: 'reprobe', id}` — a fresh probe of one remote; the outcome
101
+ * (even unreachable/auth-expired) lands in the status table server-side, so
102
+ * the caller reloads rather than interpreting the probe body.
103
+ *
104
+ * @throws Error(body.error) on a non-2xx answer (the op itself failed).
105
+ */
106
+ export declare function reprobeMachine(id: string): Promise<void>;
107
+ /**
108
+ * The standing cadence note (D18): machine status refresh rides the hub's
109
+ * 5-minute sweep — the panel renders this verbatim beside its live-fetch
110
+ * control. English copy to match the DSH UI.
111
+ */
112
+ export declare const AUTO_REFRESH_NOTE = "auto-refreshes every 5 min";
113
+ /**
114
+ * The per-machine last-fetch line, shaped from the row's `lastProbeAt`
115
+ * (the hub's status table stamp — mesh-rpc joins it on every GET).
116
+ * Pure by design (the UI passes its own `now`): headless-testable without
117
+ * jsdom, same presence contract as {@link machineVersionChip} — absent or
118
+ * non-finite stamp means "never probed" and the panel omits the line.
119
+ *
120
+ * @param lastProbeAt - epoch ms of the machine's last recorded probe.
121
+ * @param now - epoch ms the panel renders at.
122
+ * @returns "Updated 2m ago" / "Updated just now" / … , or undefined.
123
+ */
124
+ export declare function lastFetchLabel(lastProbeAt: number | undefined, now: number): string | undefined;
125
+ /**
126
+ * Client-side pre-check before a pairing submit: a parseable absolute
127
+ * http(s) URL carrying a non-empty `token` query param. The server re-parses
128
+ * authoritatively (mesh-link's parseTokenUrl); this only keeps obviously
129
+ * dead drafts off the wire.
130
+ *
131
+ * @param input - the raw token-URL draft (trim before calling).
132
+ * @returns whether the draft is submit-shaped.
133
+ */
134
+ export declare function validTokenUrl(input: string): boolean;