Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

178 lines
4.8 KiB
TypeScript

import {
selectSessionActivationPresentations,
sessionActivationPresentationMapsEqual,
type PendingActivationIntentRecord,
type AgentSessionEngine
} from "@tutti-os/agent-activity-core";
import { useCallback, useMemo, useRef } from "react";
import { type AppErrorCode } from "../../../shared/contracts/dto";
import { useEngineSelector } from "../../../shared/engine/useEngineSelector";
type AgentGUILiveState = "inactive" | "activating" | "active" | "failed";
type AgentGUIActivateInput = Parameters<
AgentSessionEngine["activateSession"]
>[0] extends infer TInput
? TInput extends { requestId: string }
? Omit<TInput, "requestId">
: never
: never;
interface UseAgentGUIActivationInput {
engine: AgentSessionEngine;
workspaceId: string;
getErrorMessage: (error: unknown) => string;
getErrorCode?: (error: unknown) => AppErrorCode | null;
}
export function isPendingNewConversationActivation(
activation:
| Pick<PendingActivationIntentRecord, "mode" | "status">
| null
| undefined
): boolean {
return (
activation?.mode === "new" &&
(activation.status === "requested" || activation.status === "uncertain")
);
}
export function isPendingNewConversationActivationForSession(
activation:
| Pick<PendingActivationIntentRecord, "agentSessionId" | "mode" | "status">
| null
| undefined,
agentSessionId: string | null | undefined
): boolean {
const normalizedSessionId = agentSessionId?.trim() ?? "";
return Boolean(
normalizedSessionId &&
activation?.agentSessionId.trim() === normalizedSessionId &&
isPendingNewConversationActivation(activation)
);
}
export function useAgentGUIActivation({
engine,
workspaceId,
getErrorMessage,
getErrorCode
}: UseAgentGUIActivationInput) {
const requestSequenceRef = useRef(0);
const presentations = useEngineSelector(
engine,
selectSessionActivationPresentations,
sessionActivationPresentationMapsEqual
);
const nextRequestId = (kind: string, agentSessionId: string): string => {
requestSequenceRef.current += 1;
return `${kind}:${workspaceId}:${agentSessionId}:${Date.now()}:${requestSequenceRef.current}`;
};
const activate = useCallback(
(input: AgentGUIActivateInput): string | null => {
const agentSessionId = input.agentSessionId.trim();
const requestId = nextRequestId("activation", agentSessionId);
return engine.activateSession({
...input,
agentSessionId,
requestId
})
? requestId
: null;
},
[engine, workspaceId]
);
const unactivate = useCallback(
(agentSessionId: string): Promise<void> => {
const normalized = agentSessionId.trim();
if (!normalized) {
return Promise.resolve();
}
engine.dispatch({
type: "activation/unactivateRequested",
agentSessionId: normalized,
commandId: nextRequestId("unactivate", normalized),
workspaceId
});
return Promise.resolve();
},
[engine, workspaceId]
);
const markFailed = useCallback(
(agentSessionId: string, error: unknown): void => {
const normalized = agentSessionId.trim();
if (!normalized) {
return;
}
engine.dispatch({
type: "activation/failureRecorded",
agentSessionId: normalized,
errorCode: getErrorCode?.(error) ?? null,
errorMessage: getErrorMessage(error),
occurredAtUnixMs: Date.now(),
requestId: nextRequestId("activation-failure", normalized),
workspaceId
});
},
[engine, getErrorCode, getErrorMessage, workspaceId]
);
const clearFailure = useCallback(
(agentSessionId: string): void => {
const normalized = agentSessionId.trim();
if (normalized) {
engine.dispatch({
type: "activation/failureCleared",
agentSessionId: normalized
});
}
},
[engine]
);
const stateFor = useCallback(
(agentSessionId: string | null | undefined): AgentGUILiveState =>
(agentSessionId ? presentations[agentSessionId]?.status : null) ??
"inactive",
[presentations]
);
const errorFor = useCallback(
(agentSessionId: string | null | undefined): string | null =>
(agentSessionId ? presentations[agentSessionId]?.errorMessage : null) ??
null,
[presentations]
);
const codeFor = useCallback(
(agentSessionId: string | null | undefined): AppErrorCode | null =>
((agentSessionId
? presentations[agentSessionId]?.errorCode
: null) as AppErrorCode | null) ?? null,
[presentations]
);
return useMemo(
() => ({
activate,
clearFailure,
markFailed,
unactivate,
stateFor,
errorFor,
codeFor
}),
[
activate,
clearFailure,
codeFor,
errorFor,
markFailed,
stateFor,
unactivate
]
);
}