Merge branch 'main' into dev
Resolve 38 conflicts preserving both sides' work: - Server: DB-based registries (dev) + WorkspaceGitService/DaemonConfigStore (main) - App: script proxy/voice MCP (dev) + pin/hide tabs/bootstrap boundary (main) - Shared: WorkspaceScriptPayload (dev) + git/GitHub runtime schemas (main) - Deleted workspace-registry-bootstrap.ts (dev's DB approach supersedes)
This commit is contained in:
@@ -585,6 +585,46 @@ describe("HostRuntimeController", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not emit legacy typed reason-code transition logs", async () => {
|
||||
const infoSpy = vi.spyOn(console, "info").mockImplementation(() => undefined);
|
||||
try {
|
||||
const host = makeHost({
|
||||
connections: [
|
||||
{
|
||||
id: "direct:lan:6767",
|
||||
type: "directTcp",
|
||||
endpoint: "lan:6767",
|
||||
},
|
||||
],
|
||||
});
|
||||
const clients: FakeDaemonClient[] = [];
|
||||
const controller = new HostRuntimeController({
|
||||
host,
|
||||
deps: makeDeps(
|
||||
{
|
||||
"direct:lan:6767": 12,
|
||||
},
|
||||
clients,
|
||||
),
|
||||
});
|
||||
|
||||
await controller.start({ autoProbe: false });
|
||||
clients[0]?.setConnectionState({
|
||||
status: "disconnected",
|
||||
reason: "transport closed",
|
||||
});
|
||||
|
||||
const transitionPayloads = infoSpy.mock.calls
|
||||
.filter((call) => call[0] === "[HostRuntimeTransition]")
|
||||
.map((call) => call[1] as { reasonCode?: string | null });
|
||||
const lastTransition = transitionPayloads[transitionPayloads.length - 1] ?? null;
|
||||
|
||||
expect(lastTransition?.reasonCode).toBeUndefined();
|
||||
} finally {
|
||||
infoSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("marks directory loading on first connection before any directory sync succeeds", async () => {
|
||||
const host = makeHost();
|
||||
const clients: FakeDaemonClient[] = [];
|
||||
@@ -1201,12 +1241,7 @@ describe("HostRuntimeStore", () => {
|
||||
archivedAt: stale.archivedAt ? new Date(stale.archivedAt) : null,
|
||||
attentionTimestamp: stale.attentionTimestamp ? new Date(stale.attentionTimestamp) : null,
|
||||
};
|
||||
return new Map([
|
||||
[
|
||||
stale.id,
|
||||
staleAgent,
|
||||
],
|
||||
]);
|
||||
return new Map([[stale.id, staleAgent]]);
|
||||
});
|
||||
|
||||
store.syncHosts([host]);
|
||||
@@ -1322,7 +1357,7 @@ describe("HostRuntimeStore", () => {
|
||||
store.syncHosts([]);
|
||||
});
|
||||
|
||||
it("keeps a custom host label when re-pairing with an advertised hostname", async () => {
|
||||
it("uses the latest advertised hostname when re-pairing an existing relay host", async () => {
|
||||
const store = new HostRuntimeStore({
|
||||
deps: {
|
||||
createClient: () => new FakeDaemonClient() as unknown as DaemonClient,
|
||||
@@ -1345,7 +1380,7 @@ describe("HostRuntimeStore", () => {
|
||||
await store.upsertConnectionFromOffer(makeOffer(), "mbp");
|
||||
|
||||
const pairedHost = store.getHosts().find((host) => host.serverId === "srv_offer");
|
||||
expect(pairedHost?.label).toBe("Custom name");
|
||||
expect(pairedHost?.label).toBe("mbp");
|
||||
|
||||
store.syncHosts([]);
|
||||
});
|
||||
|
||||
@@ -16,10 +16,7 @@ import {
|
||||
import { decodeOfferFragmentPayload, normalizeHostPort } from "@/utils/daemon-endpoints";
|
||||
import { resolveAppVersion } from "@/utils/app-version";
|
||||
import { ConnectionOfferSchema, type ConnectionOffer } from "@server/shared/connection-offer";
|
||||
import {
|
||||
shouldUseDesktopDaemon,
|
||||
startDesktopDaemon,
|
||||
} from "@/desktop/daemon/desktop-daemon";
|
||||
import { shouldUseDesktopDaemon, startDesktopDaemon } from "@/desktop/daemon/desktop-daemon";
|
||||
import { connectToDaemon } from "@/utils/test-daemon-connection";
|
||||
import { buildDaemonWebSocketUrl, buildRelayWebSocketUrl } from "@/utils/daemon-endpoints";
|
||||
import { getOrCreateClientId } from "@/utils/client-id";
|
||||
@@ -1078,8 +1075,7 @@ export class HostRuntimeController {
|
||||
}
|
||||
|
||||
const REGISTRY_STORAGE_KEY = "@paseo:daemon-registry";
|
||||
const DEFAULT_LOCALHOST_ENDPOINT =
|
||||
process.env.EXPO_PUBLIC_LOCAL_DAEMON?.trim() || "localhost:6767";
|
||||
const DEFAULT_LOCALHOST_ENDPOINT = process.env.EXPO_PUBLIC_LOCAL_DAEMON?.trim() || "localhost:6767";
|
||||
const DEFAULT_LOCALHOST_BOOTSTRAP_KEY = "@paseo:default-localhost-bootstrap-v1";
|
||||
const DEFAULT_LOCALHOST_BOOTSTRAP_TIMEOUT_MS = 2500;
|
||||
const CONNECTION_ONLINE_TIMEOUT_MS = 15_000;
|
||||
@@ -1287,10 +1283,7 @@ export class HostRuntimeStore {
|
||||
});
|
||||
}
|
||||
|
||||
async upsertConnectionFromOffer(
|
||||
offer: ConnectionOffer,
|
||||
label?: string,
|
||||
): Promise<HostProfile> {
|
||||
async upsertConnectionFromOffer(offer: ConnectionOffer, label?: string): Promise<HostProfile> {
|
||||
return this.upsertRelayConnection({
|
||||
serverId: offer.serverId,
|
||||
relayEndpoint: offer.relay.endpoint,
|
||||
@@ -1560,10 +1553,7 @@ export class HostRuntimeStore {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
if (
|
||||
snapshot.activeConnectionId === connectionId &&
|
||||
snapshot.connectionStatus === "error"
|
||||
) {
|
||||
if (snapshot.activeConnectionId === connectionId && snapshot.connectionStatus === "error") {
|
||||
return {
|
||||
ok: false,
|
||||
error: new Error(snapshot.lastError ?? "Connection failed before coming online."),
|
||||
|
||||
Reference in New Issue
Block a user