Files
tutti/packages/agent/gui/shared/agentConversation/planImplementationPresentation.ts
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

181 lines
5.4 KiB
TypeScript

import type { AgentConversationPromptVM } from "./contracts/agentConversationVM";
export const PLAN_IMPLEMENTATION_PROMPT = "Implement the plan.";
export const PLAN_IMPLEMENTATION_ACTION_IMPLEMENT = "implement";
export const PLAN_IMPLEMENTATION_ACTION_FEEDBACK = "feedback";
export const PLAN_IMPLEMENTATION_ACTION_SKIP = "skip";
export function planImplementationPromptFromPlanTurn(
planTurnId: string,
title: string
): Extract<AgentConversationPromptVM, { kind: "plan-implementation" }> {
return {
kind: "plan-implementation",
requestId: planTurnId,
title
};
}
interface PlanTimelineItem {
turnId?: string | null;
occurredAtUnixMs?: number | null;
createdAtUnixMs?: number | null;
seq?: number | null;
payload?: Record<string, unknown> | null;
}
function itemTime(item: PlanTimelineItem): number {
return item.occurredAtUnixMs ?? item.createdAtUnixMs ?? item.seq ?? 0;
}
function isPlanItem(item: PlanTimelineItem): boolean {
return item.payload?.messageKind === "plan";
}
export function latestPlanTurnId(
timelineItems: readonly PlanTimelineItem[]
): string | null {
let latestTurnId: string | null = null;
let latestTime = Number.NEGATIVE_INFINITY;
for (const item of timelineItems) {
const turnId = item.turnId?.trim();
if (!turnId) continue;
const time = itemTime(item);
if (time >= latestTime) {
latestTime = time;
latestTurnId = turnId;
}
}
if (!latestTurnId) return null;
return timelineItems.some(
(item) => item.turnId?.trim() === latestTurnId && isPlanItem(item)
)
? latestTurnId
: null;
}
export const MINIMUM_AUTO_TOKEN_BUDGET = 32_000;
export const MAXIMUM_AUTO_TOKEN_BUDGET = 2_000_000;
export interface PlanIssueExecutionProfile {
reasoningIntensity: number;
orchestrationIntensity: number;
}
export interface PlanIssueBudget {
mode: "auto" | "fixed";
tokenLimit: number;
quotaWaterlinePercent: number;
}
/**
* Remembered planning defaults chosen before a Plan turn is submitted. The
* generated plan can still provide explicit values; otherwise these values
* seed the mandatory Issue-decomposition review.
*/
export interface PlanIssueBudgetPreset {
executionProfile: PlanIssueExecutionProfile;
budget: PlanIssueBudget;
}
export function autoTokenBudget(
taskCount: number,
profile: PlanIssueExecutionProfile
): number {
const count = Number.isSafeInteger(taskCount) ? Math.max(1, taskCount) : 1;
const compiled =
16_000 +
count *
(24_000 +
Math.round(profile.reasoningIntensity) * 320 +
Math.round(profile.orchestrationIntensity) * 160);
return Math.min(
MAXIMUM_AUTO_TOKEN_BUDGET,
Math.max(MINIMUM_AUTO_TOKEN_BUDGET, compiled)
);
}
export function defaultPlanIssueBudgetPreset(): PlanIssueBudgetPreset {
const executionProfile: PlanIssueExecutionProfile = {
reasoningIntensity: 50,
orchestrationIntensity: 50
};
return {
executionProfile,
budget: {
mode: "auto",
tokenLimit: autoTokenBudget(1, executionProfile),
quotaWaterlinePercent: 10
}
};
}
/** Strict persisted-state reader; malformed values are dropped safely. */
export function normalizePlanIssueBudgetPreset(
value: unknown
): PlanIssueBudgetPreset | null {
if (!isRecord(value)) return null;
const executionProfileValue = isRecord(value.executionProfile)
? value.executionProfile
: null;
const budgetValue = isRecord(value.budget) ? value.budget : null;
if (!executionProfileValue || !budgetValue) return null;
const reasoningIntensity = percentValue(
executionProfileValue.reasoningIntensity
);
const orchestrationIntensity = percentValue(
executionProfileValue.orchestrationIntensity
);
const mode = budgetValue.mode === "fixed" ? "fixed" : "auto";
const tokenLimit = positiveInteger(budgetValue.tokenLimit);
const quotaWaterlinePercent = percentValue(budgetValue.quotaWaterlinePercent);
if (
reasoningIntensity === undefined ||
orchestrationIntensity === undefined ||
tokenLimit === undefined ||
quotaWaterlinePercent === undefined
) {
return null;
}
return {
executionProfile: { reasoningIntensity, orchestrationIntensity },
budget: { mode, tokenLimit, quotaWaterlinePercent }
};
}
export function planIssueBudgetPresetsEqual(
left: PlanIssueBudgetPreset | null | undefined,
right: PlanIssueBudgetPreset | null | undefined
): boolean {
return (
(left?.executionProfile.reasoningIntensity ?? null) ===
(right?.executionProfile.reasoningIntensity ?? null) &&
(left?.executionProfile.orchestrationIntensity ?? null) ===
(right?.executionProfile.orchestrationIntensity ?? null) &&
(left?.budget.mode ?? null) === (right?.budget.mode ?? null) &&
(left?.budget.tokenLimit ?? null) === (right?.budget.tokenLimit ?? null) &&
(left?.budget.quotaWaterlinePercent ?? null) ===
(right?.budget.quotaWaterlinePercent ?? null)
);
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function percentValue(value: unknown): number | undefined {
return typeof value === "number" &&
Number.isFinite(value) &&
Number.isInteger(value) &&
value >= 0 &&
value <= 100
? value
: undefined;
}
function positiveInteger(value: unknown): number | undefined {
return typeof value === "number" && Number.isSafeInteger(value) && value > 0
? value
: undefined;
}