merge: integrate langgraph execution runtime

# Conflicts:
#	agent-run-gateway.test.mjs
#	capabilities.mjs
#	package.json
#	server.mjs
This commit is contained in:
john
2026-07-25 00:09:15 +08:00
88 changed files with 14319 additions and 90 deletions
+341
View File
@@ -198,6 +198,290 @@ export type SystemDisclosurePolicyState = {
lastRefreshError?: string | null;
};
export type OrchestratorMode = 'off' | 'shadow' | 'canary' | 'active';
export type OrchestratorConfig = {
mode: OrchestratorMode;
primaryEngine: string;
fallbackEngine: string;
serviceUrl: string;
requestTimeoutMs: number;
rolloutPercent: number;
userAllowlist: string[];
workflowAllowlist: string[];
fallbackToNative: boolean;
requireHealthy: boolean;
executionEnabled: boolean;
};
export type OrchestratorRuntime = {
killSwitch: boolean;
configured: boolean;
effective: boolean;
reason: string | null;
executesLangGraph: boolean;
plansLangGraph: boolean;
shadowsLangGraph: boolean;
executionHandoff: {
implemented: boolean;
requested: boolean;
enabled: boolean;
reason: string | null;
environmentGate: boolean;
};
};
export type OrchestratorEngineDescriptor = {
id: string;
label: string;
kind: string;
configured: boolean;
capabilities: string[];
};
export type OrchestratorExecutorDescriptor = {
id: string;
label: string;
kind: string;
enabled: boolean;
dispatchImplemented: boolean;
status: string;
capabilities: string[];
};
export type OrchestratorConfigState = {
config: OrchestratorConfig;
configVersion: number;
updatedBy: string | null;
updatedAt: number | null;
source: string;
runtime: OrchestratorRuntime;
engines: OrchestratorEngineDescriptor[];
executors: OrchestratorExecutorDescriptor[];
};
export type OrchestratorServiceHealth = {
checkedAt: number;
ok: boolean;
status: 'healthy' | 'unhealthy' | 'unconfigured' | 'timeout' | 'unreachable' | 'fetch_unavailable';
latencyMs: number;
httpStatus: number | null;
details: {
service: string | null;
checkpoint: { kind?: string; durable?: boolean } | null;
execution: string | null;
executorGateway: {
dispatchImplemented: boolean;
executionEnabled: boolean;
store: { kind: string | null; durable: boolean } | null;
} | null;
} | null;
};
export type OrchestratorRuntimeState = OrchestratorConfigState & {
serviceHealth: OrchestratorServiceHealth;
};
export type OrchestratorShadowMetrics = {
observations: number;
successes: number;
failures: number;
successRate: number | null;
failureRate: number | null;
latencyP50Ms: number | null;
latencyP95Ms: number | null;
nativeSucceeded: number;
nativeFailed: number;
lastObservedAt: number | null;
sampled: boolean;
};
export type OrchestratorShadowRun = {
eventId: string;
runId: string;
requestId: string;
userId: string;
sessionId: string | null;
nativeStatus: string;
nativeAttempts: number;
shadowStatus: 'succeeded' | 'failed';
engine: string;
configVersion: number | null;
phase: string | null;
taskType: string | null;
synthetic: boolean;
executorAdapter: string | null;
latencyMs: number | null;
error: { code: string; message: string } | null;
observedAt: number;
nativeCompletedAt: number | null;
};
export type OrchestratorShadowRunList = {
generatedAt: number;
window: { hours: number; from: number };
metrics: OrchestratorShadowMetrics;
runs: OrchestratorShadowRun[];
};
export type OrchestratorExecutionPlan = {
eventId: string;
runId: string;
requestId: string;
userId: string;
sessionId: string | null;
nativeStatus: string;
nativeAttempts: number;
mode: string | null;
candidateEngine: string;
effectiveEngine: string;
fallbackEngine: string;
reason: string | null;
candidateReason: string | null;
configVersion: number | null;
bucket: number | null;
taskType: string | null;
dryRun: boolean;
handoffAllowed: boolean;
plannedAt: number;
nativeCompletedAt: number | null;
};
export type OrchestratorExecutionPlanMetrics = {
decisions: number;
candidateSelections: number;
candidateSelectionRate: number | null;
nativeSelections: number;
nativeSucceeded: number;
nativeFailed: number;
nativeSettledRate: number | null;
handoffAllowed: number;
distinctSessions: number;
lastPlannedAt: number | null;
candidateReasons: Array<{ value: string; count: number }>;
taskTypes: Array<{ value: string; count: number }>;
sampled: boolean;
};
export type OrchestratorExecutionPlanList = {
generatedAt: number;
window: { hours: number; from: number };
metrics: OrchestratorExecutionPlanMetrics;
plans: OrchestratorExecutionPlan[];
};
export type OrchestratorCanaryReadinessCheck = {
id: string;
passed: boolean;
actual: string | number | boolean | null;
target: string | number | boolean | null;
};
export type OrchestratorCanaryReadiness = {
generatedAt: number;
ready: boolean;
recommendation: 'keep_shadow' | 'manual_canary_review';
window: { hours: number; from: number };
thresholds: {
hours: number;
minObservations: number;
minSuccessRate: number;
maxP95LatencyMs: number;
minLatencyCoverageRate: number;
minNativeSettledRate: number;
minDistinctSessions: number;
maxHoursSinceLastObservation: number;
};
samples: {
totalObservations: number;
eligibleObservations: number;
excludedSynthetic: number;
successes: number;
failures: number;
successRate: number | null;
latencyCoverageRate: number | null;
latencyP95Ms: number | null;
nativeSettledRate: number | null;
distinctSessions: number;
lastObservedAt: number | null;
hoursSinceLastObservation: number | null;
sampled: boolean;
};
service: {
status: string | null;
latencyMs: number | null;
checkpointKind: string | null;
checkpointDurable: boolean | null;
executorJobStoreKind: string | null;
executorJobStoreDurable: boolean | null;
execution: string | null;
};
checks: OrchestratorCanaryReadinessCheck[];
blockers: string[];
failureCodes: Array<{ code: string; count: number }>;
};
export type OrchestratorShadowRunDetail = {
native: {
runId: string;
requestId: string;
userId: string;
sessionId: string | null;
status: string;
attempts: number;
error: string | null;
createdAt: number;
updatedAt: number;
startedAt: number | null;
completedAt: number | null;
};
localEvents: Array<{
eventId: string;
type: string;
data: Record<string, unknown> | null;
createdAt: number;
}>;
remote: {
available: boolean;
state: {
status?: string;
phase?: string;
plan?: Record<string, unknown>;
result?: Record<string, unknown>;
} | null;
events: Array<{
sequence?: number;
type?: string;
timestamp?: number;
data?: Record<string, unknown> | null;
}>;
error: { code: string; message: string } | null;
executorJob: {
available: boolean;
state: {
version?: string;
jobId?: string;
executor?: string;
status?: string;
reason?: string;
attempts?: number;
createdAt?: number;
updatedAt?: number;
} | null;
events: Array<{
version?: string;
eventId?: string;
jobId?: string;
sequence?: number;
type?: string;
timestamp?: number;
data?: Record<string, unknown> | null;
}>;
error: { code: string; message: string } | null;
};
};
};
// ─── Summary ──────────────────────────────────────────────────────────────────
export async function fetchAdminSummary() {
@@ -217,6 +501,63 @@ export async function updateSystemDisclosurePolicy(config: SystemDisclosurePolic
});
}
// ─── Workflow Orchestrator ───────────────────────────────────────────────────
export async function fetchOrchestratorConfig() {
return adminFetch<OrchestratorConfigState>('/admin-api/orchestrator/config');
}
export async function updateOrchestratorConfig(config: OrchestratorConfig) {
return adminFetch<OrchestratorConfigState>('/admin-api/orchestrator/config', {
method: 'PUT',
body: JSON.stringify({ config }),
});
}
export async function fetchOrchestratorRuntime() {
return adminFetch<OrchestratorRuntimeState>('/admin-api/orchestrator/runtime');
}
export async function fetchOrchestratorShadowRuns(params: {
hours?: number;
limit?: number;
status?: 'all' | 'succeeded' | 'failed';
} = {}) {
const query = new URLSearchParams();
if (params.hours) query.set('hours', String(params.hours));
if (params.limit) query.set('limit', String(params.limit));
if (params.status) query.set('status', params.status);
return adminFetch<OrchestratorShadowRunList>(
`/admin-api/orchestrator/shadow-runs?${query}`,
);
}
export async function fetchOrchestratorExecutionPlans(params: {
hours?: number;
limit?: number;
selection?: 'all' | 'candidate' | 'native';
} = {}) {
const query = new URLSearchParams();
if (params.hours) query.set('hours', String(params.hours));
if (params.limit) query.set('limit', String(params.limit));
if (params.selection) query.set('selection', params.selection);
return adminFetch<OrchestratorExecutionPlanList>(
`/admin-api/orchestrator/execution-plans?${query}`,
);
}
export async function fetchOrchestratorCanaryReadiness() {
return adminFetch<OrchestratorCanaryReadiness>(
'/admin-api/orchestrator/canary-readiness',
);
}
export async function fetchOrchestratorShadowRun(runId: string) {
return adminFetch<OrchestratorShadowRunDetail>(
`/admin-api/orchestrator/shadow-runs/${encodeURIComponent(runId)}`,
);
}
// ─── Users ────────────────────────────────────────────────────────────────────
export async function fetchAdminUsers(params: {