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
143 lines
4.1 KiB
TypeScript
143 lines
4.1 KiB
TypeScript
import {
|
|
selectTuttiModeActivationPresentation,
|
|
tuttiModeActivationPresentationsEqual,
|
|
type AgentSessionEngine,
|
|
type TuttiModeActivationPresentation
|
|
} from "@tutti-os/agent-activity-core";
|
|
import { useCallback, useMemo, useRef } from "react";
|
|
import { useEngineSelector } from "../../../shared/engine/useEngineSelector";
|
|
|
|
interface UseAgentGUITuttiModeActivationInput {
|
|
activeConversationId: string | null;
|
|
draftKey: string;
|
|
engine: AgentSessionEngine;
|
|
workspaceId: string;
|
|
}
|
|
|
|
export function resolveAgentGUITuttiModeDraftKey(
|
|
nodeId: string | null | undefined
|
|
): string {
|
|
return `agent-gui:${nodeId?.trim() || "default"}:tutti-mode:home`;
|
|
}
|
|
|
|
export function useAgentGUITuttiModeActivation({
|
|
activeConversationId,
|
|
draftKey,
|
|
engine,
|
|
workspaceId
|
|
}: UseAgentGUITuttiModeActivationInput) {
|
|
const commandSequenceRef = useRef(0);
|
|
const presentation = useEngineSelector(
|
|
engine,
|
|
useCallback(
|
|
(state) =>
|
|
selectTuttiModeActivationPresentation(
|
|
state,
|
|
activeConversationId,
|
|
draftKey
|
|
),
|
|
[activeConversationId, draftKey]
|
|
),
|
|
tuttiModeActivationPresentationsEqual
|
|
);
|
|
const updatePending = isTuttiModeActivationPending(presentation);
|
|
const setActive = useCallback(
|
|
(active: boolean): void => {
|
|
if (updatePending || presentation.active === active) return;
|
|
const agentSessionId = activeConversationId?.trim() ?? "";
|
|
if (!agentSessionId) {
|
|
engine.dispatch({
|
|
active,
|
|
draftKey,
|
|
occurredAtUnixMs: Date.now(),
|
|
type: "tuttiMode/draftSet"
|
|
});
|
|
return;
|
|
}
|
|
commandSequenceRef.current += 1;
|
|
const requestedAtUnixMs = Date.now();
|
|
engine.dispatch({
|
|
agentSessionId,
|
|
commandId: `tutti-mode:${workspaceId}:${agentSessionId}:${requestedAtUnixMs}:${commandSequenceRef.current}`,
|
|
requestedAtUnixMs,
|
|
source: active ? "slash_command" : "badge_remove",
|
|
status: active ? "active" : "inactive",
|
|
type: "tuttiMode/updateRequested",
|
|
workspaceId
|
|
});
|
|
},
|
|
[
|
|
activeConversationId,
|
|
draftKey,
|
|
engine,
|
|
presentation.active,
|
|
updatePending,
|
|
workspaceId
|
|
]
|
|
);
|
|
const retry = useCallback((): void => {
|
|
if (presentation.updateStatus !== "failed") return;
|
|
setActive(!presentation.active);
|
|
}, [presentation.active, presentation.updateStatus, setActive]);
|
|
const setPreference = useCallback(
|
|
(preference: "effect" | "speed", value: number): void => {
|
|
const agentSessionId = activeConversationId?.trim() ?? "";
|
|
if (!agentSessionId) {
|
|
engine.dispatch({
|
|
active: true,
|
|
draftKey,
|
|
occurredAtUnixMs: Date.now(),
|
|
[preference]: value,
|
|
type: "tuttiMode/draftSet"
|
|
});
|
|
return;
|
|
}
|
|
commandSequenceRef.current += 1;
|
|
const requestedAtUnixMs = Date.now();
|
|
engine.dispatch({
|
|
agentSessionId,
|
|
commandId: `tutti-mode:${workspaceId}:${agentSessionId}:${requestedAtUnixMs}:${commandSequenceRef.current}`,
|
|
[preference]: value,
|
|
requestedAtUnixMs,
|
|
source: "slash_command",
|
|
status: "active",
|
|
type: "tuttiMode/updateRequested",
|
|
workspaceId
|
|
});
|
|
},
|
|
[activeConversationId, draftKey, engine, workspaceId]
|
|
);
|
|
const setEffect = useCallback(
|
|
(value: number): void => setPreference("effect", value),
|
|
[setPreference]
|
|
);
|
|
const setSpeed = useCallback(
|
|
(value: number): void => setPreference("speed", value),
|
|
[setPreference]
|
|
);
|
|
|
|
return useMemo(
|
|
() => ({
|
|
...presentation,
|
|
effect: presentation.effect ?? presentation.orchestrationIntensity,
|
|
speed: presentation.speed ?? 50,
|
|
retry,
|
|
setActive,
|
|
setEffect,
|
|
setSpeed,
|
|
updatePending
|
|
}),
|
|
[presentation, retry, setActive, setEffect, setSpeed, updatePending]
|
|
);
|
|
}
|
|
|
|
function isTuttiModeActivationPending(
|
|
presentation: TuttiModeActivationPresentation
|
|
): boolean {
|
|
return (
|
|
presentation.updateStatus === "pending_create" ||
|
|
presentation.updateStatus === "updating" ||
|
|
presentation.updateStatus === "uncertain"
|
|
);
|
|
}
|