11import { pipe } from "effect/Function" ;
22import { useAtomValue } from "@effect/atom-react" ;
33import {
4+ ANOTHER_ADDRESS ,
45 type LinkableMachine ,
6+ linkDestination ,
57 linkRequestAnswerInput ,
68 linkRequestDefaultAccess ,
79 linkRequestDisplay ,
810 linkRequestFailureMessage ,
911 linkRequestInitialMachine ,
1012 type LinkRequestItem ,
13+ linkRequestTarget ,
1114 linkRequestTargetName ,
1215 rankMachinesByHint ,
1316} from "@t3tools/client-runtime/link-request" ;
@@ -58,9 +61,6 @@ const accessLabel = (access: AuthMcpClientAccess) =>
5861
5962const LINK_SYMBOL : AppSymbolName = { ios : "link" , android : "desktop_windows" } ;
6063
61- /** The machine list's row for linking by an address typed in. */
62- const ANOTHER_ADDRESS = "another-address" ;
63-
6464/** Whether the agent left the machine for the user to pick. */
6565const picksMachine = ( item : LinkRequestItem ) =>
6666 item . environmentId === undefined && item . url === undefined ;
@@ -141,11 +141,6 @@ function PendingLinkRequest(props: {
141141 { item . reason . trim ( ) ? (
142142 < Text className = "font-sans text-sm leading-5 text-foreground-muted" > { item . reason } </ Text >
143143 ) : null }
144- { item . label !== undefined && item . url !== undefined ? (
145- < Text className = "font-sans text-xs text-foreground-muted" numberOfLines = { 1 } >
146- { item . url }
147- </ Text >
148- ) : null }
149144 </ View >
150145 { error !== null ? (
151146 < Text
@@ -194,37 +189,6 @@ function PendingLinkRequest(props: {
194189 ) ;
195190}
196191
197- /** What the sheet links; see web's LinkRequestDialog for the same rules. */
198- type SheetTarget =
199- | { readonly kind : "none" }
200- | {
201- readonly kind : "machine" ;
202- readonly environmentId : EnvironmentId ;
203- readonly label : string ;
204- readonly urls : ReadonlyArray < string > ;
205- readonly linked : boolean ;
206- }
207- | { readonly kind : "address" } ;
208-
209- function resolveTarget (
210- item : LinkRequestItem ,
211- machines : ReadonlyArray < LinkableMachine > ,
212- choice : string | null ,
213- ) : SheetTarget {
214- if ( item . environmentId === undefined && item . url !== undefined ) return { kind : "address" } ;
215- const chosen = item . environmentId ?? choice ;
216- if ( chosen === null ) return { kind : "none" } ;
217- if ( chosen === ANOTHER_ADDRESS ) return { kind : "address" } ;
218- const machine = machines . find ( ( candidate ) => candidate . environmentId === chosen ) ;
219- return {
220- kind : "machine" ,
221- environmentId : machine ?. environmentId ?? ( chosen as EnvironmentId ) ,
222- label : machine ?. label ?? linkRequestTargetName ( item ) ,
223- urls : [ ...new Set ( [ ...( machine ?. urls ?? [ ] ) , ...( item . url === undefined ? [ ] : [ item . url ] ) ] ) ] ,
224- linked : machine ?. linked ?? false ,
225- } ;
226- }
227-
228192function LinkRequestSheet ( props : {
229193 readonly environmentId : EnvironmentId ;
230194 readonly item : LinkRequestItem ;
@@ -251,17 +215,22 @@ function LinkRequestSheet(props: {
251215 reportDefect : false ,
252216 } ) ;
253217 const selected = choice ?? linkRequestInitialMachine ( item , machines ) ;
254- const target = resolveTarget ( item , machines , selected ) ;
218+ const target = linkRequestTarget ( item , machines , selected ) ;
255219 const targetName = target . kind === "machine" ? target . label : linkRequestTargetName ( item ) ;
256- // This phone can mint a code there when it is connected to that environment
257- // with a session that may create pairing links.
258220 const targetId = target . kind === "machine" ? target . environmentId : null ;
259221 const connected = usePreparedConnection ( targetId ) ;
260222 const mayMint = useEnvironmentScope ( targetId , AuthAccessWriteScope ) ;
261- const canMint =
262- targetId !== null && Option . isSome ( connected ) && mayMint && ! mintFailed . has ( targetId ) ;
263223 const needsAddress =
264224 target . kind === "address" || ( target . kind === "machine" && target . urls . length === 0 ) ;
225+ // This phone mints a code there when it is connected with a session that may
226+ // create pairing links, and only for its own addresses: anything can answer
227+ // as that machine at one typed in, so that one gets a code the user fetched.
228+ const canMint =
229+ targetId !== null &&
230+ ! needsAddress &&
231+ Option . isSome ( connected ) &&
232+ mayMint &&
233+ ! mintFailed . has ( targetId ) ;
265234 const useExisting = target . kind === "machine" && target . linked ;
266235 const ready =
267236 target . kind !== "none" &&
@@ -288,10 +257,7 @@ function LinkRequestSheet(props: {
288257 }
289258 return linkRequestAnswerInput ( item , {
290259 type : "link" ,
291- target :
292- target . kind === "address"
293- ? { url : address }
294- : { ...target , urls : needsAddress ? [ address . trim ( ) ] : target . urls } ,
260+ target : target . kind === "machine" && target . urls . length > 0 ? target : { url : address } ,
295261 access,
296262 pairingCode : code ,
297263 } ) ;
@@ -335,12 +301,27 @@ function LinkRequestSheet(props: {
335301 Agents here can then launch, message and wait on threads there. It appears in that
336302 machine's Connections, where it can be revoked.
337303 </ Text >
338- { ! pickMachine && item . url !== undefined ? (
304+ { item . url !== undefined && target . kind === "machine" ? (
339305 < Text className = "font-sans text-xs text-foreground-muted" numberOfLines = { 1 } >
340306 { item . url }
341307 </ Text >
342308 ) : null }
343309 </ View >
310+ { needsAddress && ! useExisting && address . trim ( ) ? (
311+ < View
312+ accessibilityRole = "alert"
313+ className = "gap-1 rounded-xl border border-warning-border bg-warning p-3"
314+ >
315+ < Text className = "font-t3-bold text-sm text-warning-foreground" > Check this address</ Text >
316+ < Text className = "font-sans text-xs leading-snug text-warning-foreground" >
317+ This app cannot confirm it is one of your machines. The pairing code you paste is sent
318+ there.
319+ </ Text >
320+ < Text selectable className = "font-sans text-xs leading-snug text-warning-foreground" >
321+ { linkDestination ( address ) }
322+ </ Text >
323+ </ View >
324+ ) : null }
344325 { pickMachine ? (
345326 < SettingsSection title = "Machine" >
346327 { machines . map ( ( machine , index ) => (
@@ -369,7 +350,7 @@ function LinkRequestSheet(props: {
369350 />
370351 </ SettingsSection >
371352 ) : null }
372- { needsAddress && ! ( item . url !== undefined && item . environmentId === undefined ) ? (
353+ { needsAddress && item . url === undefined ? (
373354 < View className = "gap-2" >
374355 < TextInput
375356 accessibilityLabel = "Address"
0 commit comments