diff --git a/app/components/debug-event.tsx b/app/components/debug-event.tsx index 1ea512b1..8d0d32a3 100644 --- a/app/components/debug-event.tsx +++ b/app/components/debug-event.tsx @@ -10,31 +10,45 @@ import { import { useAuth } from "@clerk/nextjs"; import { ClientInferResponseBody } from "@ts-rest/core"; import { startCase } from "lodash"; -import { Info } from "lucide-react"; +import { Info, Blocks } from "lucide-react"; import { useState } from "react"; import { ReadOnlyJSON } from "./read-only-json"; const sanitizedKey: { [key: string]: string } = { - targetFn: "function", + targetFn: "Function", + workflowId: "Run ID", + clusterId: "Cluster ID", }; +function formatDateTime(date: string | Date) { + return new Date(date).toLocaleString(undefined, { + year: "numeric", + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }); +} + export function DebugEvent({ event, clusterId, + msSincePreviousEvent, }: { event: ClientInferResponseBody< typeof contract.getRunTimeline, 200 >["activity"][number]; clusterId: string; + msSincePreviousEvent: number; }) { const [eventMeta, setEventMeta] = useState(null); const [isLoading, setIsLoading] = useState(false); - const { getToken } = useAuth(); const fetchEventMeta = async () => { - if (eventMeta) return; // Don't fetch if we already have the data + if (eventMeta) return; setIsLoading(true); try { const response = await client.getEventMeta({ @@ -52,17 +66,26 @@ export function DebugEvent({ console.error("Error fetching event metadata:", error); } finally { setIsLoading(false); - ``; } }; return ( -
-
-
-

- {startCase(event.type)} -

+
+
+ +
+
+
+

+ {startCase(event.type)} +

+ + {formatDateTime(event.createdAt)} + + {msSincePreviousEvent ? ` +${msSincePreviousEvent / 1000}s` : ""} + + +
- Event Metadata + +
+
+ +
+
+
{startCase(event.type)}
+
+ {formatDateTime(event.createdAt)} +
+
+
+
-
- {isLoading ? ( -

Loading metadata...

- ) : eventMeta ? ( - - ) : ( -

No metadata available

- )} + +
+
+
+
+ +
+
+
Event Details
+
+ Event ID: {event.id} +
+
+
+ +
+ {Object.entries(event).map(([key, value]) => ( +
+
+ {sanitizedKey[key] ?? startCase(key)} +
+
+ {value instanceof Date + ? formatDateTime(value) + : String(value) || "—"} +
+
+ ))} +
+
+ +
+
+
+ +
+
+
Metadata
+
+ Additional event information +
+
+
+ + {isLoading ? ( +
+

+ Loading metadata... +

+
+ ) : eventMeta ? ( + + ) : ( +
+

+ No metadata available +

+
+ )} +
-
- {Object.entries(event) - .filter( - ([key, value]) => - key !== "id" && key !== "createdAt" && key !== "type" && !!value, - ) - .map(([key, value]) => ( - - - {sanitizedKey[key] ?? startCase(key)}: - - - {value instanceof Date ? value.toISOString() : String(value)} - - - ))} -
); } diff --git a/app/components/events-overlay.tsx b/app/components/events-overlay.tsx index 7d65582c..7083ab6e 100644 --- a/app/components/events-overlay.tsx +++ b/app/components/events-overlay.tsx @@ -81,17 +81,17 @@ const typeToText: { [key: string]: string } = { jobCreated: "Job was created.", jobStatusRequest: `Caller asked for the status of the job.`, jobReceived: `Function was received by the machine for execution.`, - jobResulted: `Function execution concluded.`, + functionResulted: `Function execution concluded.`, jobStalled: `Function execution did not complete within the expected time frame. The function is marked as stalled.`, jobRecovered: `Function execution was recovered after being marked as stalled.`, jobStalledTooManyTimes: `Function execution did not complete within the expected time frame too many times. The execution has resulted in a failure.`, agentMessage: `Agent message produced.`, agentEnd: `Agent workflow concluded.`, jobAcknowledged: `Job was acknowledged by the machine.`, - agentTool: `Agent is invoking a tool.`, + callingFunction: `Agent is invoking a tool.`, humanMessage: `Human sent a message.`, machineRegistered: `Machine registered with the control plane.`, - agentToolError: `Invoked tool produced an error.`, + functionErrored: `Invoked tool produced an error.`, modelInvocation: `A call was made to the model.`, }; @@ -129,7 +129,7 @@ const chartConfig: ChartConfig = { label: "Job Received", color: "hsl(210, 100%, 70%)", // Blue }, - jobResulted: { + functionResulted: { label: "Job Resulted", color: "hsl(210, 100%, 70%)", // Blue }, @@ -157,7 +157,7 @@ const chartConfig: ChartConfig = { label: "Job Acknowledged", color: "hsl(210, 100%, 70%)", // Blue }, - agentTool: { + callingFunction: { label: "Agent Tool", color: "hsl(210, 100%, 70%)", // Blue }, @@ -169,7 +169,7 @@ const chartConfig: ChartConfig = { label: "Machine Registered", color: "hsl(210, 100%, 70%)", // Blue }, - agentToolError: { + functionErrored: { label: "Agent Tool Error", color: "hsl(0, 100%, 70%)", // Red }, @@ -183,7 +183,7 @@ const getEventCountsByTime = (events: Event[]) => { if (events.length === 0) return []; const earliestEventTime = new Date( - Math.min(...events.map((event) => new Date(event.createdAt).getTime())), + Math.min(...events.map((event) => new Date(event.createdAt).getTime())) ); const timeNow = new Date(); @@ -195,7 +195,7 @@ const getEventCountsByTime = (events: Event[]) => { const bucketStartTimes = Array.from({ length: bucketCount }, (_, i) => { const time = new Date(earliestEventTime); time.setMilliseconds( - time.getMilliseconds() + i * (differenceInMs / bucketCount), + time.getMilliseconds() + i * (differenceInMs / bucketCount) ); return time; }); @@ -208,13 +208,10 @@ const getEventCountsByTime = (events: Event[]) => { }); return { date: t.toISOString(), - ...eventsInBucket.reduce( - (acc, event) => { - acc[event.type] = (acc[event.type] || 0) + 1; - return acc; - }, - {} as Record, - ), + ...eventsInBucket.reduce((acc, event) => { + acc[event.type] = (acc[event.type] || 0) + 1; + return acc; + }, {} as Record), }; }); }; @@ -252,7 +249,7 @@ function EventsOverlay({ Object.entries(query).map(([key, value]) => ({ key: key as FilterKey, value: value as string, - })), + })) ); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -269,13 +266,10 @@ function EventsOverlay({ params: { clusterId, }, - query: filters.reduce( - (acc, filter) => { - acc[filter.key] = filter.value; - return acc; - }, - {} as Partial>, - ), + query: filters.reduce((acc, filter) => { + acc[filter.key] = filter.value; + return acc; + }, {} as Partial>), }); if (response.status === 200) { @@ -289,7 +283,7 @@ function EventsOverlay({ setLoading(false); } }, - [clusterId, getToken], + [clusterId, getToken] ); useEffect(() => { @@ -317,7 +311,7 @@ function EventsOverlay({ const updated = [...prev]; newFilters.forEach((newFilter) => { const existingIndex = updated.findIndex( - (f) => f.key === newFilter.key && f.value === newFilter.value, + (f) => f.key === newFilter.key && f.value === newFilter.value ); if (existingIndex === -1) { updated.push(newFilter); @@ -331,8 +325,8 @@ function EventsOverlay({ setFilters((prev) => prev.filter( (f) => - !(f.key === filterToRemove.key && f.value === filterToRemove.value), - ), + !(f.key === filterToRemove.key && f.value === filterToRemove.value) + ) ); }; diff --git a/app/components/workflow.tsx b/app/components/workflow.tsx index f923732c..b3e28398 100644 --- a/app/components/workflow.tsx +++ b/app/components/workflow.tsx @@ -308,14 +308,27 @@ export function Run({ })) || []; const activityElements = - runTimeline?.activity.map((a) => ({ - element: ( - - - - ), - timestamp: new Date(a.createdAt).getTime(), - })) || []; + runTimeline?.activity + .sort((a, b) => (a.createdAt > b.createdAt ? 1 : -1)) + .map((a, index) => ({ + element: ( + + 0 + ? new Date(a.createdAt).getTime() - + new Date( + runTimeline?.activity[index - 1]?.createdAt ?? 0 + ).getTime() + : 0 + } + /> + + ), + timestamp: new Date(a.createdAt).getTime(), + })) || []; const testHeader = runTimeline?.run.test === true diff --git a/control-plane/src/modules/calls/router.ts b/control-plane/src/modules/calls/router.ts index 783c313c..1cbb3787 100644 --- a/control-plane/src/modules/calls/router.ts +++ b/control-plane/src/modules/calls/router.ts @@ -120,6 +120,12 @@ export const callsRouter = initServer().router( sdkLanguage: request.headers["x-machine-sdk-language"], xForwardedFor: request.headers["x-forwarded-for"], ip: request.request.ip, + }).catch((e) => { + // don't fail the request if the machine upsert fails + + logger.error("Failed to upsert machine", { + error: e, + }); }), jobs.persistJobResult({ owner: machine, diff --git a/control-plane/src/modules/jobs/persist-result.ts b/control-plane/src/modules/jobs/persist-result.ts index 6c1c3e73..fbb21bd2 100644 --- a/control-plane/src/modules/jobs/persist-result.ts +++ b/control-plane/src/modules/jobs/persist-result.ts @@ -1,20 +1,9 @@ -import { - and, - eq, - gt, - isNotNull, - isNull, - lt, - lte, - ne, - or, - sql, -} from "drizzle-orm"; +import { and, eq, gt, isNotNull, isNull, lt, lte, or, sql } from "drizzle-orm"; import * as data from "../data"; import * as events from "../observability/events"; import { logger } from "../observability/logger"; -import { resumeRun } from "../workflows/workflows"; import { upsertResultKeys } from "../tool-metadata"; +import { resumeRun } from "../workflows/workflows"; type PersistResultParams = { result: string; @@ -88,7 +77,7 @@ export async function persistJobResult({ result, result_type: resultType, resulted_at: sql`now()`, - function_execution_time_ms: functionExecutionTime, + function_execution_time_ms: functionExecutionTime || null, status: "success", }) .where( @@ -111,15 +100,15 @@ export async function persistJobResult({ jobId, }); events.write({ - type: "jobResultedButNotPersisted", + type: "functionResultedButNotPersisted", service: updateResult[0]?.service, clusterId: owner.clusterId, jobId, machineId, targetFn: updateResult[0]?.targetFn, resultType, + workflowId: updateResult[0]?.runId ?? undefined, meta: { - result, functionExecutionTime, }, }); @@ -148,15 +137,15 @@ export async function persistJobResult({ }); events.write({ - type: "jobResulted", + type: "functionResulted", service: updateResult[0]?.service, clusterId: owner.clusterId, jobId, machineId, targetFn: updateResult[0]?.targetFn, resultType, + workflowId: updateResult[0]?.runId ?? undefined, meta: { - result, functionExecutionTime, }, }); @@ -198,6 +187,7 @@ export async function selfHealJobs(params?: { machineStallTimeout?: number }) { targetFn: data.jobs.target_fn, clusterId: data.jobs.cluster_id, remainingAttempts: data.jobs.remaining_attempts, + runId: data.jobs.workflow_id, }); const stalledMachines = await data.db @@ -228,6 +218,7 @@ export async function selfHealJobs(params?: { machineStallTimeout?: number }) { target_fn: string; cluster_id: string; remaining_attempts: number; + runId: string | undefined; }>( sql` UPDATE jobs as j @@ -286,6 +277,7 @@ export async function selfHealJobs(params?: { machineStallTimeout?: number }) { clusterId: row.clusterId, jobId: row.id, type: "jobStalled", + workflowId: row.runId ?? undefined, meta: { attemptsRemaining: row.remainingAttempts ?? undefined, reason: "timeout", @@ -299,6 +291,7 @@ export async function selfHealJobs(params?: { machineStallTimeout?: number }) { clusterId: row.cluster_id, jobId: row.id, type: "jobStalled", + workflowId: row.runId ?? undefined, meta: { attemptsRemaining: row.remaining_attempts ?? undefined, reason: "machine stalled", diff --git a/control-plane/src/modules/models/index.ts b/control-plane/src/modules/models/index.ts index 0be0884a..57de00bf 100644 --- a/control-plane/src/modules/models/index.ts +++ b/control-plane/src/modules/models/index.ts @@ -358,14 +358,12 @@ export const buildMockModel = ({ } const parsed = options.schema.safeParse( - JSON.parse( - mockResponses[responseCount] - ) + JSON.parse(mockResponses[responseCount]), ); // Sleep for between 500 and 1500 ms await new Promise((resolve) => - setTimeout(resolve, Math.random() * 1000 + 500) + setTimeout(resolve, Math.random() * 1000 + 500), ); if (!parsed.success) { @@ -385,10 +383,9 @@ export const buildMockModel = ({ data: parsed.data, }, }; - }, }; -} +}; const trackModelUsage = async ({ runId, diff --git a/control-plane/src/modules/observability/events.test.ts b/control-plane/src/modules/observability/events.test.ts index 0b0ea8cd..b16d056e 100644 --- a/control-plane/src/modules/observability/events.test.ts +++ b/control-plane/src/modules/observability/events.test.ts @@ -117,7 +117,7 @@ describe("event-aggregation", () => { expect(activity[0].type).toEqual("jobCreated"); expect(activity[1].type).toEqual("jobAcknowledged"); - expect(activity[activity.length - 1].type).toEqual("jobResulted"); + expect(activity[activity.length - 1].type).toEqual("functionResulted"); } }); }); diff --git a/control-plane/src/modules/observability/events.ts b/control-plane/src/modules/observability/events.ts index 94384de3..a8a95fee 100644 --- a/control-plane/src/modules/observability/events.ts +++ b/control-plane/src/modules/observability/events.ts @@ -1,15 +1,15 @@ +import { and, desc, eq, gte, SQL, sql } from "drizzle-orm"; import { ulid } from "ulid"; +import { NotFoundError } from "../../utilities/errors"; import { db, events as eventsTable } from "../data"; import { logger } from "./logger"; -import { eq, and, gte, SQL, desc, or, sql } from "drizzle-orm"; -import { NotFoundError } from "../../utilities/errors"; export type EventTypes = | "jobCreated" | "jobAcknowledged" | "jobStatusRequest" - | "jobResulted" - | "jobResultedButNotPersisted" + | "functionResulted" + | "functionResultedButNotPersisted" | "jobStalled" | "jobStalledTooManyTimes" | "jobRecovered" @@ -18,21 +18,15 @@ export type EventTypes = | "machineStalled" | "machineResourceProbe" | "modelInvocation" - | "functionInvocation" - | "encryptedAgentMessage" - | "workflowScheduleCreated" - | "workflowScheduleRemoved" - | "listenerAttached" - | "listenerDetached" - | "listenerNotificationReceived" | "humanMessage" | "systemMessage" | "agentMessage" - | "agentTool" - | "agentToolError" + | "callingFunction" + | "functionErrored" | "workflowFeedbackSubmitted" | "resultSummarized" - | "knowledgeArtifactsAccessed"; + | "knowledgeArtifactsAccessed" + | "functionRegistrySearchCompleted"; type Event = { clusterId: string; @@ -75,6 +69,8 @@ type Event = { originalResultSize?: number; summarySize?: number; artifacts?: string[]; + duration?: number; + tools?: string[]; }; }; @@ -88,7 +84,7 @@ export const userAttentionLevels = { const typeToUserAttentionLevel = { jobCreated: 10, jobAcknowledged: 10, - jobResulted: 10, + functionResulted: 10, jobStalled: 30, jobStalledTooManyTimes: 40, jobRecovered: 30, @@ -97,8 +93,8 @@ const typeToUserAttentionLevel = { machineResourceProbe: 10, modelInvocation: 10, functionInvocation: 10, - agentTool: 10, - agentToolError: 10, + callingFunction: 10, + functionErrored: 10, resultSummarized: 20, knowledgeArtifactsAccessed: 20, } as const; @@ -251,6 +247,38 @@ export const getActivityByWorkflowIdForUserAttentionLevel = async (params: { return results; }; +export const getActivityForTimeline = async (params: { + clusterId: string; + runId: string; + after?: string; +}) => { + const results = await db + .select({ + id: eventsTable.id, + clusterId: eventsTable.cluster_id, + type: eventsTable.type, + jobId: eventsTable.job_id, + machineId: eventsTable.machine_id, + service: eventsTable.service, + createdAt: eventsTable.created_at, + targetFn: eventsTable.target_fn, + resultType: eventsTable.result_type, + status: eventsTable.status, + workflowId: eventsTable.run_id, + }) + .from(eventsTable) + .where( + and( + eq(eventsTable.cluster_id, params.clusterId), + eq(eventsTable.run_id, params.runId), + ), + ) + .limit(100) + .orderBy(desc(eventsTable.created_at)); + + return results; +}; + export const getMetaForActivity = async (params: { clusterId: string; eventId: string; diff --git a/control-plane/src/modules/workflows/agent/nodes/tool-call.ts b/control-plane/src/modules/workflows/agent/nodes/tool-call.ts index 34d6e5da..c1222410 100644 --- a/control-plane/src/modules/workflows/agent/nodes/tool-call.ts +++ b/control-plane/src/modules/workflows/agent/nodes/tool-call.ts @@ -9,6 +9,7 @@ import { AgentError, InvalidJobArgumentsError, } from "../../../../utilities/errors"; +import { customerTelemetry } from "../../../customer-telemetry"; import * as events from "../../../observability/events"; import { logger } from "../../../observability/logger"; import { addAttributes, withSpan } from "../../../observability/tracer"; @@ -17,8 +18,6 @@ import { Run } from "../../workflows"; import { ToolFetcher } from "../agent"; import { WorkflowAgentState } from "../state"; import { SpecialResultTypes, parseFunctionResponse } from "../tools/functions"; -import { z } from "zod"; -import { customerTelemetry } from "../../../customer-telemetry"; export const TOOL_CALL_NODE_NAME = "action"; @@ -187,7 +186,7 @@ const _handleToolCall = async ( }; events.write({ - type: "agentTool", + type: "callingFunction", clusterId: workflow.clusterId, workflowId: workflow.id, toolName, @@ -218,7 +217,7 @@ const _handleToolCall = async ( if (response.resultType === "rejection") { events.write({ - type: "agentToolError", + type: "functionErrored", clusterId: workflow.clusterId, workflowId: workflow.id, meta: { @@ -292,7 +291,7 @@ const _handleToolCall = async ( } catch (error) { if (error instanceof ToolInputParsingException) { events.write({ - type: "agentToolError", + type: "functionErrored", clusterId: workflow.clusterId, workflowId: workflow.id, meta: { @@ -350,7 +349,7 @@ const _handleToolCall = async ( if (error instanceof InvalidJobArgumentsError) { events.write({ - type: "agentToolError", + type: "functionErrored", clusterId: workflow.clusterId, workflowId: workflow.id, meta: { diff --git a/control-plane/src/modules/workflows/agent/run.ts b/control-plane/src/modules/workflows/agent/run.ts index cf272bb9..b8bd07df 100644 --- a/control-plane/src/modules/workflows/agent/run.ts +++ b/control-plane/src/modules/workflows/agent/run.ts @@ -31,6 +31,7 @@ import { getClusterInternalTools } from "./tools/cluster-internal-tools"; import { buildCurrentDateTimeTool } from "./tools/date-time"; import { CURRENT_DATE_TIME_TOOL_NAME } from "./tools/date-time"; import { env } from "../../../utilities/env"; +import { events } from "../../observability/events"; /** * Run a workflow from the most recent saved state @@ -73,16 +74,19 @@ export const run = async (run: Run) => { serviceFunctionEmbeddingId({ serviceName: service.name, functionName: f.name, - }) + }), ); - }) + }), ); const mockToolsMap: Record = await buildMockTools(run); let mockModelResponses; - if (!!env.LOAD_TEST_CLUSTER_ID && run.clusterId === env.LOAD_TEST_CLUSTER_ID) { + if ( + !!env.LOAD_TEST_CLUSTER_ID && + run.clusterId === env.LOAD_TEST_CLUSTER_ID + ) { logger.info("Mocking model responses for load test"); //https://github.com/inferablehq/inferable/blob/main/load-tests/script.js @@ -92,17 +96,17 @@ export const run = async (run: Run) => { invocations: [ { toolName: "default_searchHaystack", - input: {} - } - ] + input: {}, + }, + ], }), JSON.stringify({ done: true, result: { - word: "needle" - } - }) - ] + word: "needle", + }, + }), + ]; } const app = await createWorkflowAgent({ @@ -130,7 +134,7 @@ export const run = async (run: Run) => { const serviceFunctionDetails = await embeddableServiceFunction.getEntity( run.clusterId, "service-function", - toolCall.toolName + toolCall.toolName, ); if (serviceFunctionDetails) { @@ -155,7 +159,7 @@ export const run = async (run: Run) => { // optimistically embed the next search query // this is not critical to the workflow, so we can do it in the background embedSearchQuery( - state.messages.map((m) => JSON.stringify(m.data)).join(" ") + state.messages.map((m) => JSON.stringify(m.data)).join(" "), ); } @@ -190,7 +194,7 @@ export const run = async (run: Run) => { }, { recursionLimit: 100, - } + }, ); const parsedOutput = z @@ -262,7 +266,7 @@ async function findRelatedFunctionTools(workflow: Run, search: string) { workflow.clusterId, "service-function", search, - 30 + 30, ) : []; @@ -278,7 +282,7 @@ async function findRelatedFunctionTools(workflow: Run, search: string) { const metadata = await getToolMetadata( workflow.clusterId, toolDetails.serviceName, - toolDetails.functionName + toolDetails.functionName, ); const contextArr = []; @@ -291,7 +295,7 @@ async function findRelatedFunctionTools(workflow: Run, search: string) { contextArr.push( `${metadata.resultKeys .slice(0, 10) - .map((k) => k.key)}` + .map((k) => k.key)}`, ); } @@ -300,7 +304,7 @@ async function findRelatedFunctionTools(workflow: Run, search: string) { functionName: toolDetails.functionName, toolContext: contextArr.join("\n\n"), }; - }) + }), ); const selectedTools = relatedTools.map((toolDetails) => @@ -311,13 +315,13 @@ async function findRelatedFunctionTools(workflow: Run, search: string) { toolContexts.find( (c) => c?.serviceName === toolDetails.serviceName && - c?.functionName === toolDetails.functionName + c?.functionName === toolDetails.functionName, )?.toolContext, ] .filter(Boolean) .join("\n\n"), schema: toolDetails.schema, - }) + }), ); return selectedTools; @@ -334,6 +338,7 @@ const buildAdditionalContext = async (workflow: Run) => { }; export const findRelevantTools = async (state: WorkflowAgentState) => { + const start = Date.now(); const workflow = state.workflow; const tools: DynamicStructuredTool[] = []; @@ -359,12 +364,12 @@ export const findRelevantTools = async (state: WorkflowAgentState) => { const serviceFunctionDetails = await embeddableServiceFunction.getEntity( workflow.clusterId, "service-function", - tool + tool, ); if (!serviceFunctionDetails) { throw new Error( - `Tool ${tool} not found in cluster ${workflow.clusterId}` + `Tool ${tool} not found in cluster ${workflow.clusterId}`, ); } @@ -372,23 +377,32 @@ export const findRelevantTools = async (state: WorkflowAgentState) => { buildAbstractServiceFunctionTool({ ...serviceFunctionDetails, schema: serviceFunctionDetails.schema, - }) + }), ); } } else { const found = await findRelatedFunctionTools( workflow, - state.messages.map((m) => JSON.stringify(m.data)).join(" ") + state.messages.map((m) => JSON.stringify(m.data)).join(" "), ); tools.push(...found); - const accessKnowledgeArtifactsTool = await buildAccessKnowledgeArtifacts( - workflow - ); + const accessKnowledgeArtifactsTool = + await buildAccessKnowledgeArtifacts(workflow); // When tools are not specified, attach all internalTools tools.push(accessKnowledgeArtifactsTool); + + events.write({ + type: "functionRegistrySearchCompleted", + workflowId: workflow.id, + clusterId: workflow.clusterId, + meta: { + duration: Date.now() - start, + tools: tools.map((t) => t.name), + }, + }); } return tools; @@ -402,7 +416,7 @@ export const buildMockTools = async (workflow: Run) => { if (!workflow.test) { logger.warn( - "Workflow is not marked as test enabled but contains mocks. Mocks will be ignored." + "Workflow is not marked as test enabled but contains mocks. Mocks will be ignored.", ); return mocks; } @@ -430,7 +444,7 @@ export const buildMockTools = async (workflow: Run) => { } const serviceDefinition = serviceDefinitions.find( - (sd) => sd.name === serviceName + (sd) => sd.name === serviceName, ); if (!serviceDefinition) { @@ -439,13 +453,13 @@ export const buildMockTools = async (workflow: Run) => { { key, serviceName, - } + }, ); continue; } const functionDefinition = serviceDefinition.functions?.find( - (f) => f.name === functionName + (f) => f.name === functionName, ); if (!functionDefinition) { @@ -455,7 +469,7 @@ export const buildMockTools = async (workflow: Run) => { key, serviceName, functionName, - } + }, ); continue; } diff --git a/control-plane/src/modules/workflows/router.ts b/control-plane/src/modules/workflows/router.ts index ebb5d548..2d5e5e65 100644 --- a/control-plane/src/modules/workflows/router.ts +++ b/control-plane/src/modules/workflows/router.ts @@ -372,10 +372,9 @@ export const runsRouter = initServer().router( runId, after: messagesAfter, }), - events.getActivityByWorkflowIdForUserAttentionLevel({ + events.getActivityForTimeline({ clusterId, runId, - userAttentionLevel: "info", after: activityAfter, }), getJobsForWorkflow({