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

229 lines
7.2 KiB
TypeScript

import { createContext, useContext, type JSX, type ReactNode } from "react";
import type { AgentActivityComposerSettingOption } from "@tutti-os/agent-activity-core";
import type { TuttiModePlanReviewSnapshot } from "./tuttiModePlan/tuttiModePlanPanelProjection";
export interface TuttiModePlanReviewUpdate {
kind: "workflow_updated";
workspaceId: string;
workflowId: string;
sourceSessionId: string;
checkpointId: string;
changeKind:
| "proposal_created"
| "revision_created"
| "checkpoint_decided"
| "operation_updated";
}
export interface TuttiModePlanReviewConnectionRestored {
kind: "connection_restored";
workspaceId: string;
}
/**
* A root turn of the source session settled. The host derives this from the
* daemon's canonical turn fan-out and relays it as a read-repair trigger: a
* plan proposed mid-turn announces itself through one workflow event, and if
* that single event is lost no later workflow signal re-reads review state.
*/
export interface TuttiModePlanReviewSessionSettled {
kind: "session_settled";
workspaceId: string;
sourceSessionId: string;
}
/** Cached assignment catalogs changed for exact Agent Targets. */
export interface TuttiModePlanAssignmentOptionsInvalidated {
kind: "assignment_options_invalidated";
workspaceId: string;
agentTargetIds: readonly string[];
}
export type TuttiModePlanReviewInvalidation =
| TuttiModePlanReviewUpdate
| TuttiModePlanReviewConnectionRestored
| TuttiModePlanReviewSessionSettled
| TuttiModePlanAssignmentOptionsInvalidated;
export interface TuttiModePlanTaskAssignmentInput {
taskId: string;
agentTargetId?: string | null;
modelPlanId?: string | null;
model?: string | null;
permissionModeId?: string | null;
reasoningEffort?: string | null;
parallelizable?: boolean | null;
autoAccept?: boolean | null;
}
export interface TuttiModePlanReviewDecisionInput {
workspaceId: string;
workflowId: string;
checkpointId: string;
decision: "accepted" | "rejected" | "canceled";
decidedBy: string;
reason?: string | null;
/** Per-task overrides; only meaningful with an accepted task review. */
taskAssignments?: readonly TuttiModePlanTaskAssignmentInput[];
}
export interface TuttiModePlanAssignmentAgentOption {
agentTargetId: string;
label: string;
}
export interface TuttiModePlanAssignmentAgentDetail {
/** Provider-native models usable without a model plan. */
models: readonly AgentActivityComposerSettingOption[];
modelPlans: readonly {
modelPlanId: string;
label: string;
models: readonly AgentActivityComposerSettingOption[];
}[];
permissionModes: readonly { id: string; label: string }[];
reasoningEfforts: readonly AgentActivityComposerSettingOption[];
}
export interface TuttiPlanIssueTaskSnapshot {
taskId: string;
title: string;
content: string;
status: string;
sortIndex: number;
parallelizable: boolean;
autoAccept: boolean;
dependencyTaskIds: string[];
}
/** Read-only snapshot of the Issue a session's accepted plan materialized. */
export interface TuttiPlanIssueSnapshot {
workflowId: string;
sourceTurnId: string | null;
issueId: string;
topicId: string;
title: string;
/** Durable Issue execution gate; paused graphs are not active work. */
dispatchPaused: boolean;
tasks: TuttiPlanIssueTaskSnapshot[];
}
/**
* An accepted plan whose create_issue operation durably failed. The
* conversation must surface this instead of rendering nothing: there is no
* pending checkpoint (the review panel is gone) and no Issue (the issue panel
* never appears), so silence would hide the failure entirely.
*/
export interface TuttiPlanIssueMaterializationFailure {
workflowId: string;
sourceTurnId: string | null;
errorMessage: string | null;
}
export type TuttiPlanIssueQueryResult =
| { kind: "issue"; issue: TuttiPlanIssueSnapshot }
| ({ kind: "materialization_failed" } & TuttiPlanIssueMaterializationFailure)
| null;
/**
* Source for the embedded plan-issue panel in the conversation.
* The host resolves "the Issue this session's accepted plan created", relays
* live issue updates, and exposes only daemon-owned product commands. Task
* accept/rework actions remain source-Agent prompts rather than generic Issue
* mutations.
*/
export interface TuttiPlanIssueSource {
getSessionPlanIssue(input: {
workspaceId: string;
sourceSessionId: string;
}): Promise<TuttiPlanIssueQueryResult>;
subscribeIssueUpdates(
workspaceId: string,
listener: (update: { issueId: string }) => void
): () => void;
/**
* Stops the Issue's execution: pauses future dispatch and cancels every
* running task run. Idempotent; the daemon owns the cascade.
*/
cancelExecution(input: {
workspaceId: string;
issueId: string;
}): Promise<void>;
/**
* Resolves the delegate agent session that ran (or is running) a task's
* latest run, so a task card can jump straight into that conversation.
* Null when the task has not launched yet.
*/
resolveTaskSession(input: {
workspaceId: string;
issueId: string;
taskId: string;
}): Promise<{ agentSessionId: string } | null>;
}
/**
* Option catalogs for per-task assignment editing. The desktop host reuses
* its agent directory and composer capability catalogs; the panel never
* hardcodes providers or modes.
*/
export interface TuttiModePlanAssignmentOptionsSource {
/**
* Returns the last successful workspace directory, including stale data.
* Hosts may omit this when they do not retain a query cache.
*/
readAgents?(input: {
workspaceId: string;
}): readonly TuttiModePlanAssignmentAgentOption[] | null;
listAgents(input: {
workspaceId: string;
}): Promise<readonly TuttiModePlanAssignmentAgentOption[]>;
/**
* Returns the last successful target catalog, including stale data, so a
* refresh never replaces usable selectors with a loading placeholder.
*/
readAgentOptions?(input: {
workspaceId: string;
agentTargetId: string;
}): TuttiModePlanAssignmentAgentDetail | null;
loadAgentOptions(input: {
workspaceId: string;
agentTargetId: string;
}): Promise<TuttiModePlanAssignmentAgentDetail>;
}
export interface TuttiModePlanReviewRuntime {
listPending(input: {
workspaceId: string;
sourceSessionId: string;
}): Promise<readonly TuttiModePlanReviewSnapshot[]>;
decide(input: TuttiModePlanReviewDecisionInput): Promise<void>;
subscribe(
workspaceId: string,
listener: (update: TuttiModePlanReviewInvalidation) => void
): () => void;
/** Optional; the panel degrades to read-only assignment display without it. */
assignmentOptions?: TuttiModePlanAssignmentOptionsSource;
/** Optional; without it the embedded plan-issue panel never renders. */
planIssues?: TuttiPlanIssueSource;
}
const TuttiModePlanReviewRuntimeContext =
createContext<TuttiModePlanReviewRuntime | null>(null);
export function TuttiModePlanReviewRuntimeProvider({
children,
runtime
}: {
children: ReactNode;
runtime?: TuttiModePlanReviewRuntime | null;
}): JSX.Element {
return (
<TuttiModePlanReviewRuntimeContext.Provider value={runtime ?? null}>
{children}
</TuttiModePlanReviewRuntimeContext.Provider>
);
}
export function useOptionalTuttiModePlanReviewRuntime(): TuttiModePlanReviewRuntime | null {
return useContext(TuttiModePlanReviewRuntimeContext);
}