feat: add execution foundation contracts

This commit is contained in:
kris
2026-04-02 21:37:10 +08:00
parent 5e23e1d408
commit e348d6cc5d
4 changed files with 197 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
import type {
ExecutionBackendDescription,
ExecutionImmediateResult,
ExecutionQueuedResult,
ExecutionRequest,
} from "@/lib/execution/types";
export interface ExecutionBackend {
backendId: string;
canHandle(input: ExecutionRequest): Promise<boolean> | boolean;
execute(input: ExecutionRequest): Promise<ExecutionQueuedResult | ExecutionImmediateResult>;
describe(input: ExecutionRequest): Promise<ExecutionBackendDescription>;
}

View File

@@ -0,0 +1,4 @@
export interface OrchestrationBackend {
backendId: string;
describe(): Promise<{ backendId: string; label: string }>;
}

104
src/lib/execution/types.ts Normal file
View File

@@ -0,0 +1,104 @@
import type { ReasoningEffort } from "@/lib/boss-data";
export type ExecutionRequestKind =
| "master_agent_reply"
| "thread_reply"
| "dispatch_execution"
| "attachment_analysis";
export interface ExecutionRequest {
kind: ExecutionRequestKind;
projectId: string;
requestMessageId: string;
body: string;
requestedByAccount?: string;
requestedByLabel?: string;
taskId?: string;
targetThreadId?: string;
targetProjectId?: string;
modelOverride?: string;
reasoningEffortOverride?: ReasoningEffort;
}
export interface ExecutionQueuedResult {
status: "queued" | "running";
taskId: string;
backendId: string;
sessionId?: string;
}
export interface ExecutionImmediateCompletedResult {
status: "completed";
backendId: string;
output: string;
}
export interface ExecutionImmediateFailedResult {
status: "failed";
backendId: string;
error: string;
}
export type ExecutionImmediateResult =
| ExecutionImmediateCompletedResult
| ExecutionImmediateFailedResult;
export interface ExecutionBackendDescription {
backendId: string;
label: string;
mode: "local" | "remote" | "api";
}
export function createExecutionRequest(input: ExecutionRequest): ExecutionRequest {
return {
kind: input.kind,
projectId: input.projectId,
requestMessageId: input.requestMessageId,
body: input.body,
requestedByAccount: input.requestedByAccount ?? undefined,
requestedByLabel: input.requestedByLabel ?? undefined,
taskId: input.taskId ?? undefined,
targetThreadId: input.targetThreadId ?? undefined,
targetProjectId: input.targetProjectId ?? undefined,
modelOverride: input.modelOverride ?? undefined,
reasoningEffortOverride: input.reasoningEffortOverride ?? undefined,
};
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
function hasStringProperty(value: Record<string, unknown>, key: string): boolean {
return typeof value[key] === "string" && value[key].length > 0;
}
export function isQueuedExecutionResult(value: unknown): value is ExecutionQueuedResult {
if (!isRecord(value)) {
return false;
}
if (value.status !== "queued" && value.status !== "running") {
return false;
}
return hasStringProperty(value, "taskId") && hasStringProperty(value, "backendId");
}
export function isImmediateExecutionResult(
value: unknown,
): value is ExecutionImmediateResult {
if (!isRecord(value)) {
return false;
}
if (value.status === "completed") {
return hasStringProperty(value, "backendId") && hasStringProperty(value, "output");
}
if (value.status === "failed") {
return hasStringProperty(value, "backendId") && hasStringProperty(value, "error");
}
return false;
}