124 lines
6.4 KiB
TypeScript
124 lines
6.4 KiB
TypeScript
import type { CanvasAgentSnapshot } from "@/lib/canvas/canvas-agent-ops";
|
|
import type { AgentReasoningEffort } from "@/stores/use-agent-store";
|
|
|
|
type AgentConfigResponse = { ok?: boolean; protocolVersion?: number; url?: string; token?: string; hasToken?: boolean };
|
|
|
|
export type AgentSkillScope = "user" | "repo" | "system" | "admin";
|
|
export type AgentSkillInterface = { displayName?: string | null; shortDescription?: string | null; defaultPrompt?: string | null };
|
|
export type AgentSkillSummary = {
|
|
name: string;
|
|
description: string;
|
|
shortDescription?: string | null;
|
|
interface?: AgentSkillInterface | null;
|
|
dependencies?: unknown;
|
|
path: string;
|
|
scope: AgentSkillScope;
|
|
enabled: boolean;
|
|
managed: boolean;
|
|
};
|
|
export type AgentSkillDetail = {
|
|
name: string;
|
|
description: string;
|
|
instructions: string;
|
|
interface?: AgentSkillInterface | null;
|
|
path: string;
|
|
managed: true;
|
|
revision: string;
|
|
};
|
|
export type AgentSkillInput = { name?: string; description: string; instructions: string; interface?: AgentSkillInterface | null; expectedRevision?: string };
|
|
export type AgentSkillDraft = { name: string; displayName: string; description: string; instructions: string; shortDescription: string; defaultPrompt: string };
|
|
export type AgentSkillDraftInput = { source: "conversation" | "canvas"; threadId: string; clientId: string; model?: string; effort?: AgentReasoningEffort };
|
|
export type AgentSkillsResponse = { ok?: boolean; data?: AgentSkillSummary[]; errors?: unknown[] };
|
|
export type AgentSkillResponse = { ok?: boolean; data?: AgentSkillDetail };
|
|
export type AgentSkillDraftResponse = { ok?: boolean; data?: AgentSkillDraft };
|
|
|
|
export async function postState(endpoint: string, token: string, clientId: string, snapshot: CanvasAgentSnapshot | null) {
|
|
try {
|
|
const response = await fetch(`${endpoint}/canvas/state?token=${encodeURIComponent(token)}&clientId=${encodeURIComponent(clientId)}`, {
|
|
method: "POST",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify(snapshot ? { ...snapshot, hasCanvas: true } : { hasCanvas: false }),
|
|
});
|
|
return response.ok;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export async function activateAgentClient(endpoint: string, token: string, clientId: string) {
|
|
try {
|
|
await fetch(`${endpoint}/canvas/activate?token=${encodeURIComponent(token)}&clientId=${encodeURIComponent(clientId)}`, { method: "POST" });
|
|
} catch {}
|
|
}
|
|
|
|
export async function postToolResult(endpoint: string, token: string, clientId: string, body: { requestId: string; result?: unknown; error?: string }) {
|
|
await fetchAgentJson(endpoint, token, `/canvas/result?clientId=${encodeURIComponent(clientId)}`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) });
|
|
}
|
|
|
|
export async function postCodexApproval(endpoint: string, token: string, requestId: string, decision: "accept" | "acceptForSession" | "decline") {
|
|
await fetchAgentJson(endpoint, token, "/agent/codex/approval", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ requestId, decision }) });
|
|
}
|
|
|
|
export async function interruptCodexTurn(endpoint: string, token: string, threadId?: string) {
|
|
await fetchAgentJson(endpoint, token, "/agent/codex/interrupt", jsonPost({ threadId }));
|
|
}
|
|
|
|
export async function acknowledgeCodexHistory(endpoint: string, token: string, threadId: string, turnIds: string[]) {
|
|
await fetchAgentJson(endpoint, token, "/agent/codex/history/ack", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ threadId, turnIds }) });
|
|
}
|
|
|
|
export async function revealAgentLocalFile(endpoint: string, token: string, path: string) {
|
|
await fetchAgentJson(endpoint, token, "/agent/local-file/reveal", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ path }) });
|
|
}
|
|
|
|
export function fetchCodexSkills(endpoint: string, token: string, forceReload = false) {
|
|
return fetchAgentJson<AgentSkillsResponse>(endpoint, token, `/agent/codex/skills${forceReload ? "?forceReload=1" : ""}`);
|
|
}
|
|
|
|
export function fetchCodexSkill(endpoint: string, token: string, name: string) {
|
|
return fetchAgentJson<AgentSkillResponse>(endpoint, token, `/agent/codex/skills/${encodeURIComponent(name)}`);
|
|
}
|
|
|
|
export function createCodexSkill(endpoint: string, token: string, input: AgentSkillInput) {
|
|
return fetchAgentJson<AgentSkillResponse>(endpoint, token, "/agent/codex/skills", jsonPost(input));
|
|
}
|
|
|
|
export function createCodexSkillDraft(endpoint: string, token: string, input: AgentSkillDraftInput) {
|
|
return fetchAgentJson<AgentSkillDraftResponse>(endpoint, token, "/agent/codex/skills/draft", jsonPost(input));
|
|
}
|
|
|
|
export function updateCodexSkill(endpoint: string, token: string, name: string, input: AgentSkillInput) {
|
|
return fetchAgentJson<AgentSkillResponse>(endpoint, token, `/agent/codex/skills/${encodeURIComponent(name)}`, jsonPost(input));
|
|
}
|
|
|
|
export function deleteCodexSkill(endpoint: string, token: string, name: string, expectedRevision: string) {
|
|
return fetchAgentJson<{ ok?: boolean }>(endpoint, token, `/agent/codex/skills/${encodeURIComponent(name)}/delete`, jsonPost({ expectedRevision }));
|
|
}
|
|
|
|
export function setCodexSkillEnabled(endpoint: string, token: string, skill: Pick<AgentSkillSummary, "name" | "path">, enabled: boolean) {
|
|
return fetchAgentJson<{ ok?: boolean }>(endpoint, token, `/agent/codex/skills/${encodeURIComponent(skill.name)}/enabled`, jsonPost({ ...skill, enabled }));
|
|
}
|
|
|
|
export async function fetchAgentJson<T>(endpoint: string, token: string, path: string, init?: RequestInit) {
|
|
const url = `${endpoint}${path}${path.includes("?") ? "&" : "?"}token=${encodeURIComponent(token)}`;
|
|
const res = await fetch(url, init);
|
|
const data = (await res.json().catch(() => ({}))) as T & { error?: string; msg?: string };
|
|
if (!res.ok) throw new Error(data.error || data.msg || "本地 Agent 请求失败");
|
|
return data;
|
|
}
|
|
|
|
export async function discoverAgentConfig(endpoint: string) {
|
|
try {
|
|
const res = await fetch(`${endpoint}/config`);
|
|
if (!res.ok) return null;
|
|
const data = (await res.json()) as AgentConfigResponse;
|
|
return data.ok ? data : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function jsonPost(body: unknown): RequestInit {
|
|
return { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) };
|
|
}
|