mirror of
https://github.com/getpaseo/paseo.git
synced 2026-08-15 04:42:45 +00:00
Merge remote-tracking branch 'origin/main' into merge/main-into-dev
# Conflicts: # CLAUDE.md # nix/package.nix # packages/app/src/components/combined-model-selector.tsx # packages/app/src/hooks/use-sidebar-workspaces-list.ts # packages/app/src/screens/workspace/workspace-screen.tsx # packages/app/src/stores/session-store.test.ts # packages/server/src/client/daemon-client.ts # packages/server/src/server/agent/agent-manager.ts # packages/server/src/server/session.ts # packages/server/src/server/session.workspace-git-watch.test.ts # packages/server/src/server/session.workspaces.test.ts # packages/server/src/shared/messages.ts
This commit is contained in:
@@ -5,6 +5,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useClientActivity } from "@/hooks/use-client-activity";
|
||||
import { usePushTokenRegistration } from "@/hooks/use-push-token-registration";
|
||||
import { clearArchiveAgentPending } from "@/hooks/use-archive-agent";
|
||||
import { prefetchProvidersSnapshot } from "@/hooks/use-providers-snapshot";
|
||||
import { generateMessageId, type StreamItem } from "@/types/stream";
|
||||
import {
|
||||
processTimelineResponse,
|
||||
@@ -32,6 +33,7 @@ import {
|
||||
type Agent,
|
||||
type SessionState,
|
||||
type WorkspaceDescriptor,
|
||||
mergeWorkspaceSnapshotWithExisting,
|
||||
normalizeWorkspaceDescriptor,
|
||||
} from "@/stores/session-store";
|
||||
import { useDraftStore } from "@/stores/draft-store";
|
||||
@@ -69,6 +71,22 @@ export type {
|
||||
const HISTORY_STALE_AFTER_MS = 60_000;
|
||||
const AUTHORITATIVE_REVALIDATION_DEBOUNCE_MS = 300;
|
||||
|
||||
function hasAgentUsageChanged(
|
||||
incomingUsage: Agent["lastUsage"] | undefined,
|
||||
currentUsage: Agent["lastUsage"] | undefined,
|
||||
): boolean {
|
||||
const keys: Array<keyof NonNullable<Agent["lastUsage"]>> = [
|
||||
"inputTokens",
|
||||
"outputTokens",
|
||||
"cachedInputTokens",
|
||||
"totalCostUsd",
|
||||
"contextWindowMaxTokens",
|
||||
"contextWindowUsedTokens",
|
||||
];
|
||||
|
||||
return keys.some((key) => incomingUsage?.[key] !== currentUsage?.[key]);
|
||||
}
|
||||
|
||||
type AudioOutputPayload = Extract<SessionOutboundMessage, { type: "audio_output" }>["payload"];
|
||||
|
||||
interface BufferedAudioChunk {
|
||||
@@ -318,6 +336,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
|
||||
}
|
||||
|
||||
const workspaces = new Map<string, WorkspaceDescriptor>();
|
||||
const existingWorkspaces = useSessionStore.getState().sessions[serverId]?.workspaces;
|
||||
let cursor: string | null = null;
|
||||
let includeSubscribe = options?.subscribe ?? false;
|
||||
|
||||
@@ -333,7 +352,13 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
|
||||
|
||||
for (const entry of payload.entries) {
|
||||
const workspace = normalizeWorkspaceDescriptor(entry);
|
||||
workspaces.set(workspace.id, workspace);
|
||||
workspaces.set(
|
||||
workspace.id,
|
||||
mergeWorkspaceSnapshotWithExisting({
|
||||
incoming: workspace,
|
||||
existing: existingWorkspaces?.get(workspace.id),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (!payload.pageInfo.hasMore || !payload.pageInfo.nextCursor) {
|
||||
@@ -358,6 +383,15 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
|
||||
setAgents(serverId, (prev) => {
|
||||
const current = prev.get(agent.id);
|
||||
if (current && agent.updatedAt.getTime() < current.updatedAt.getTime()) {
|
||||
const hasUsageUpdate = hasAgentUsageChanged(agent.lastUsage, current.lastUsage);
|
||||
if (hasUsageUpdate) {
|
||||
const next = new Map(prev);
|
||||
next.set(agent.id, {
|
||||
...current,
|
||||
lastUsage: agent.lastUsage,
|
||||
});
|
||||
return next;
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
const next = new Map(prev);
|
||||
@@ -611,6 +645,34 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
|
||||
updateSessionClient(serverId, client);
|
||||
}, [serverId, client, updateSessionClient]);
|
||||
|
||||
useEffect(() => {
|
||||
const serverInfo = client.getLastServerInfoMessage();
|
||||
if (!serverInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateSessionServerInfo(serverId, {
|
||||
serverId: serverInfo.serverId,
|
||||
hostname: serverInfo.hostname,
|
||||
version: serverInfo.version,
|
||||
...(serverInfo.capabilities ? { capabilities: serverInfo.capabilities } : {}),
|
||||
...(serverInfo.features ? { features: serverInfo.features } : {}),
|
||||
});
|
||||
}, [client, serverId, updateSessionServerInfo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
const serverInfo = client.getLastServerInfoMessage();
|
||||
if (!serverInfo?.features?.providersSnapshot) {
|
||||
return;
|
||||
}
|
||||
|
||||
prefetchProvidersSnapshot(serverId, client);
|
||||
}, [client, isConnected, serverId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!voiceRuntime) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user