113 lines
3.2 KiB
TypeScript
113 lines
3.2 KiB
TypeScript
import type { StrategyAngle } from "./types";
|
||
|
||
export type StrategyAgentCategory =
|
||
| "intent"
|
||
| "angle"
|
||
| "judge"
|
||
| "solution";
|
||
|
||
export interface StrategyAgent {
|
||
id: string;
|
||
category: StrategyAgentCategory;
|
||
fixed: boolean;
|
||
enabled: boolean;
|
||
sort_order: number;
|
||
name: string;
|
||
description: string;
|
||
model: string | null;
|
||
soul: string | null;
|
||
skills: string[] | null;
|
||
created_at: string | null;
|
||
updated_at: string | null;
|
||
}
|
||
|
||
const STRATEGY_ANGLE_PREFIX = "strategy-selection-angle-";
|
||
|
||
const LEGACY_ANGLE_IDS: Record<string, string> = {
|
||
"strategy-selection-angle-governance": "governance",
|
||
"strategy-selection-angle-diplomacy": "diplomacy",
|
||
"strategy-selection-angle-economy": "economy",
|
||
"strategy-selection-angle-security": "security",
|
||
"strategy-selection-angle-public-opinion": "public_opinion",
|
||
"strategy-selection-angle-law-policy": "law_policy",
|
||
};
|
||
|
||
const LEGACY_SHORT_NAMES: Record<string, string> = {
|
||
"strategy-selection-angle-governance": "治理",
|
||
"strategy-selection-angle-diplomacy": "外交",
|
||
"strategy-selection-angle-economy": "经济",
|
||
"strategy-selection-angle-security": "安全",
|
||
"strategy-selection-angle-public-opinion": "民生",
|
||
"strategy-selection-angle-law-policy": "法律",
|
||
};
|
||
|
||
const LEGACY_ACCENTS: Record<string, string> = {
|
||
"strategy-selection-angle-governance": "#6d5dfc",
|
||
"strategy-selection-angle-diplomacy": "#0ea5e9",
|
||
"strategy-selection-angle-economy": "#10b981",
|
||
"strategy-selection-angle-security": "#f97316",
|
||
"strategy-selection-angle-public-opinion": "#ec4899",
|
||
"strategy-selection-angle-law-policy": "#a855f7",
|
||
};
|
||
|
||
const ACCENT_PALETTE = [
|
||
"#2563eb",
|
||
"#0891b2",
|
||
"#059669",
|
||
"#ca8a04",
|
||
"#ea580c",
|
||
"#dc2626",
|
||
"#db2777",
|
||
"#7c3aed",
|
||
] as const;
|
||
|
||
function stableAccent(id: string) {
|
||
if (LEGACY_ACCENTS[id]) return LEGACY_ACCENTS[id];
|
||
let hash = 2166136261;
|
||
for (let index = 0; index < id.length; index += 1) {
|
||
hash ^= id.charCodeAt(index);
|
||
hash = Math.imul(hash, 16777619);
|
||
}
|
||
return ACCENT_PALETTE[(hash >>> 0) % ACCENT_PALETTE.length];
|
||
}
|
||
|
||
function displayAngleName(name: string) {
|
||
const cleaned = name
|
||
.trim()
|
||
.replace(/^策略(?:分析)?视角[·•::\s-]*/, "")
|
||
.replace(/(?:分析)?智能体$/, "")
|
||
.trim();
|
||
return cleaned || name.trim() || "未命名视角";
|
||
}
|
||
|
||
/** Map the public API shape to the workbench's stable angle representation. */
|
||
export function strategyAgentToAngle(
|
||
agent: StrategyAgent,
|
||
): StrategyAngle | null {
|
||
if (agent.category !== "angle") return null;
|
||
const suffix = agent.id.startsWith(STRATEGY_ANGLE_PREFIX)
|
||
? agent.id.slice(STRATEGY_ANGLE_PREFIX.length)
|
||
: agent.id;
|
||
const name = displayAngleName(agent.name);
|
||
return {
|
||
id: LEGACY_ANGLE_IDS[agent.id] ?? suffix,
|
||
agentId: agent.id,
|
||
name,
|
||
shortName:
|
||
LEGACY_SHORT_NAMES[agent.id] ??
|
||
name.split(/[与和及、·/]/u, 1)[0].slice(0, 6),
|
||
description: agent.description,
|
||
accent: stableAccent(agent.id),
|
||
enabled: agent.enabled,
|
||
};
|
||
}
|
||
|
||
export function strategyAgentsToAngles(
|
||
agents: StrategyAgent[],
|
||
): StrategyAngle[] {
|
||
return agents.flatMap((agent) => {
|
||
const angle = strategyAgentToAngle(agent);
|
||
return angle ? [angle] : [];
|
||
});
|
||
}
|