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

199 lines
6.1 KiB
TypeScript

import {
useCallback,
type Dispatch,
type RefObject,
type SetStateAction
} from "react";
import {
selectEngineQueuedPrompt,
type AgentSessionEngine
} from "@tutti-os/agent-activity-core";
import type { AgentGUIRuntime } from "../../../agentActivityRuntime";
import type { AgentComposerDraft } from "../model/agentGuiNodeTypes";
import {
agentComposerDraftImages,
agentPromptContentToComposerDraft,
updateAgentComposerDraft
} from "../model/agentComposerDraft";
import { resolveAgentComposerDraftScopeKey } from "../model/agentComposerDraftScope";
import { QueuedPromptImageLoadOwner } from "../queuedPromptImageLoadOwner";
import { createAgentGUIConversationId } from "./agentGuiController.promptHelpers";
export interface UseAgentGUIQueueActionsInput {
activeConversationIdRef: RefObject<string | null>;
agentActivityRuntime: AgentGUIRuntime;
sessionEngine: AgentSessionEngine;
setDraftByScopeKey: Dispatch<
SetStateAction<Record<string, AgentComposerDraft>>
>;
workspaceId: string;
}
/** Owns queued-prompt mutations without coupling them to session activation. */
export function useAgentGUIQueueActions({
activeConversationIdRef,
agentActivityRuntime,
sessionEngine,
setDraftByScopeKey,
workspaceId
}: UseAgentGUIQueueActionsInput) {
const removeQueuedPrompt = useCallback(
(queuedPromptId: string) => {
const agentSessionId = activeConversationIdRef.current;
const normalizedQueuedPromptId = queuedPromptId.trim();
if (!agentSessionId || !normalizedQueuedPromptId) {
return;
}
const queuedPrompt = selectEngineQueuedPrompt(
sessionEngine.getSnapshot(),
agentSessionId,
normalizedQueuedPromptId
);
sessionEngine.dispatch(
queuedPrompt?.clientSubmitId
? {
agentSessionId,
clientSubmitId: queuedPrompt.clientSubmitId,
type: "submit/canceled"
}
: {
agentSessionId,
promptId: normalizedQueuedPromptId,
type: "queue/removed"
}
);
},
[activeConversationIdRef, sessionEngine]
);
const editQueuedPrompt = useCallback(
(queuedPromptId: string) => {
const agentSessionId = activeConversationIdRef.current;
const normalizedQueuedPromptId = queuedPromptId.trim();
if (!agentSessionId || !normalizedQueuedPromptId) {
return;
}
const queuedPrompt = selectEngineQueuedPrompt(
sessionEngine.getSnapshot(),
agentSessionId,
normalizedQueuedPromptId
);
if (!queuedPrompt) {
return;
}
const draftScopeKey = resolveAgentComposerDraftScopeKey({
agentSessionId
});
const restoredDraft = agentPromptContentToComposerDraft(
queuedPrompt.content,
`restore-${queuedPrompt.id}`
);
sessionEngine.dispatch(
queuedPrompt.clientSubmitId
? {
agentSessionId,
clientSubmitId: queuedPrompt.clientSubmitId,
type: "submit/canceled"
}
: {
agentSessionId,
promptId: normalizedQueuedPromptId,
type: "queue/removed"
}
);
setDraftByScopeKey((current) => ({
...current,
[draftScopeKey]: restoredDraft
}));
for (const restoredImage of agentComposerDraftImages(restoredDraft)) {
const attachmentId = restoredImage.attachmentId?.trim() ?? "";
const path = restoredImage.path?.trim() ?? "";
if (restoredImage.previewUrl || (!attachmentId && !path)) {
continue;
}
const owner = new QueuedPromptImageLoadOwner(
{
agentSessionId,
attachmentId,
imageKey: restoredImage.id,
mimeType: restoredImage.mimeType,
name: restoredImage.name,
path,
remoteUrl: restoredImage.url?.trim() ?? "",
runtime: agentActivityRuntime,
workspaceId
},
(source) => {
if (!source) {
return;
}
setDraftByScopeKey((current) => {
const currentDraft = current[draftScopeKey];
if (!currentDraft) {
return current;
}
let updated = false;
const images = agentComposerDraftImages(currentDraft).map(
(currentImage) => {
if (
currentImage.id !== restoredImage.id ||
currentImage.previewUrl ||
currentImage.attachmentId !== restoredImage.attachmentId ||
currentImage.path !== restoredImage.path ||
currentImage.url !== restoredImage.url
) {
return currentImage;
}
updated = true;
return { ...currentImage, previewUrl: source };
}
);
return updated
? {
...current,
[draftScopeKey]: updateAgentComposerDraft(currentDraft, {
images
})
}
: current;
});
}
);
owner.start();
}
},
[
activeConversationIdRef,
agentActivityRuntime,
sessionEngine,
setDraftByScopeKey,
workspaceId
]
);
const sendQueuedPromptNext = useCallback(
(queuedPromptId: string) => {
const agentSessionId = activeConversationIdRef.current;
const normalizedQueuedPromptId = queuedPromptId.trim();
if (!agentSessionId || !normalizedQueuedPromptId) {
return;
}
sessionEngine.dispatch({
agentSessionId,
awaitingTurnExpiresAtUnixMs: Date.now() + 30_000,
cancelCommandId: createAgentGUIConversationId(),
promptId: normalizedQueuedPromptId,
timeoutMs: 30_000,
type: "queue/sendNowRequested"
});
},
[activeConversationIdRef, sessionEngine]
);
return {
editQueuedPrompt,
removeQueuedPrompt,
sendQueuedPromptNext
};
}