Skip to content

Commit dd1e609

Browse files
Merge remote-tracking branch 'origin/main' into fix/issue-27325
2 parents fd48df6 + c90b678 commit dd1e609

34 files changed

Lines changed: 1425 additions & 235 deletions

‎.github/workflows/ci.yml‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,16 @@ jobs:
140140
- name: Start installing browser secret helper build libraries
141141
if: needs.changes.outputs.build != 'false'
142142
run: |
143-
sudo sed -i 's|http://|https://|g' /etc/apt/blacksmith-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources
143+
# Fetch only the indexes these main and universe packages need. The full set is ~42 MB,
144+
# which a slow mirror can stretch past the wait below.
145+
sudo sed -i -e 's|http://|https://|g' -e 's/^Components: .*/Components: main universe/' \
146+
/etc/apt/blacksmith-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources
144147
(
145148
set +e
146-
sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config xvfb
149+
sudo apt-get update -o Acquire::Languages=none \
150+
-o Acquire::IndexTargets::deb::DEP-11::DefaultEnabled=false \
151+
-o Acquire::IndexTargets::deb::CNF::DefaultEnabled=false &&
152+
sudo apt-get install -y libsecret-1-dev pkg-config xvfb
147153
echo "$?" > "$RUNNER_TEMP/apt-status"
148154
) > "$RUNNER_TEMP/apt.log" 2>&1 < /dev/null &
149155
@@ -287,10 +293,16 @@ jobs:
287293
# the background while Vite+ installs; the step before the tests waits for it.
288294
- name: Start installing browser secret helper build libraries
289295
run: |
290-
sudo sed -i 's|http://|https://|g' /etc/apt/blacksmith-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources
296+
# Fetch only the indexes these main and universe packages need. The full set is ~42 MB,
297+
# which a slow mirror can stretch past the wait below.
298+
sudo sed -i -e 's|http://|https://|g' -e 's/^Components: .*/Components: main universe/' \
299+
/etc/apt/blacksmith-ubuntu-mirrors.txt /etc/apt/sources.list.d/ubuntu.sources
291300
(
292301
set +e
293-
sudo apt-get update && sudo apt-get install -y libsecret-1-dev pkg-config
302+
sudo apt-get update -o Acquire::Languages=none \
303+
-o Acquire::IndexTargets::deb::DEP-11::DefaultEnabled=false \
304+
-o Acquire::IndexTargets::deb::CNF::DefaultEnabled=false &&
305+
sudo apt-get install -y libsecret-1-dev pkg-config
294306
echo "$?" > "$RUNNER_TEMP/apt-status"
295307
) > "$RUNNER_TEMP/apt.log" 2>&1 < /dev/null &
296308

‎apps/mobile/src/features/threads/LinkRequestCard.tsx‎

Lines changed: 31 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { pipe } from "effect/Function";
22
import { useAtomValue } from "@effect/atom-react";
33
import {
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

5962
const 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. */
6565
const 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-
228192
function 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"

‎apps/mobile/src/lib/threadActivity.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {
22
ThreadPendingApproval,
33
ThreadPendingUserInput,
44
} from "@t3tools/client-runtime/state/thread-requests";
5+
import { linkRequestTargetName } from "@t3tools/client-runtime/link-request";
56
import { turnItemIsWorkspacePreparation } from "@t3tools/client-runtime/state/turn-item-presentation";
67
import type { ThreadCheckpointSummary } from "@t3tools/client-runtime/state/thread-checkpoints";
78
import { formatSubagentDisplayTitle } from "@t3tools/client-runtime/state/subagent-display";
@@ -624,7 +625,7 @@ function itemSummary(
624625
case "secret_request":
625626
return item.label;
626627
case "link_request":
627-
return `Link ${item.label ?? item.url ?? "an environment"}`;
628+
return `Link ${linkRequestTargetName(item)}`;
628629
case "dynamic_tool": {
629630
const classified = classifyToolActivity({
630631
itemType: "dynamic_tool_call",

‎apps/server/src/mcp/OrchestratorMcpService.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -969,8 +969,8 @@ function turnItemText(item: OrchestrationV2TurnItem): string | null {
969969
return `Asked the user for ${item.label}: ${item.secretStatus}.`;
970970
case "link_request":
971971
return item.linkStatus === "linked"
972-
? `Linked ${item.linkedLabel ?? item.label ?? item.url ?? "an environment"} (${item.linkedAccess}).`
973-
: `Asked the user to link ${item.label ?? item.url ?? "an environment"}: ${item.linkStatus}.`;
972+
? `Linked ${item.linkedLabel ?? item.url ?? "an environment"} (${item.linkedAccess}).`
973+
: `Asked the user to link ${item.url ?? "an environment"}: ${item.linkStatus}.`;
974974
case "subagent":
975975
return item.result ?? item.progress ?? item.prompt;
976976
case "dynamic_tool":

0 commit comments

Comments
 (0)