Files
WeHub Mirror 6bf8bebf51
CI / Test and Build (push) Failing after 1s
CI / Migrate Dev DB (push) Has been skipped
CI / Migrate DB (push) Has been skipped
CodeQL / Analyze actions (push) Has been cancelled
CodeQL / Analyze javascript-typescript (push) Has been cancelled
CI / Detect Version (push) Has been cancelled
CI / Detect Desktop Changes (push) Has been cancelled
CI / Build AMD64 (blacksmith-2vcpu-ubuntu-2404, ./docker/cron.Dockerfile, ubuntu-latest, ghcr.io/simstudioai/cron) (push) Has been cancelled
CI / Build AMD64 (blacksmith-2vcpu-ubuntu-2404, ./docker/db.Dockerfile, ECR_MIGRATIONS, ubuntu-latest, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (blacksmith-4vcpu-ubuntu-2404, ./docker/pii.Dockerfile, ECR_PII, ubuntu-latest, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (blacksmith-4vcpu-ubuntu-2404, ./docker/realtime.Dockerfile, ECR_REALTIME, ubuntu-latest, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build AMD64 (blacksmith-8vcpu-ubuntu-2404, ./docker/app.Dockerfile, ECR_APP, linux-x64-8-core, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/cron.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/cron) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/db.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/pii.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-4vcpu-ubuntu-2404-arm, ./docker/realtime.Dockerfile, ubuntu-24.04-arm, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (blacksmith-8vcpu-ubuntu-2404-arm, ./docker/app.Dockerfile, linux-arm64-8-core, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
Helm Chart / Lint, test, and validate chart (push) Has been cancelled
Helm Chart / Chart version bumped (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Build Dev ECR (blacksmith-8vcpu-ubuntu-2404, ./docker/app.Dockerfile, ECR_APP, linux-x64-8-core) (push) Has been cancelled
CI / Promote Images (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/cron) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build Dev ECR (blacksmith-2vcpu-ubuntu-2404, ./docker/db.Dockerfile, ECR_MIGRATIONS, ubuntu-latest) (push) Has been cancelled
CI / Build Dev ECR (blacksmith-4vcpu-ubuntu-2404, ./docker/pii.Dockerfile, ECR_PII, ubuntu-latest) (push) Has been cancelled
CI / Build Dev ECR (blacksmith-4vcpu-ubuntu-2404, ./docker/realtime.Dockerfile, ECR_REALTIME, ubuntu-latest) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Check Desktop Signing Secrets (push) Has been cancelled
CI / Desktop Release (push) Has been cancelled
CI / Create Desktop Prerelease (push) Has been cancelled
CI / Desktop Prerelease Build (push) Has been cancelled
CI / Publish Desktop Prerelease (push) Has been cancelled
CI / Prune Desktop Prereleases (push) Has been cancelled
Helm Chart / Install on kind and run helm test (push) Has been cancelled
WeHub snapshot of cb28d14c6f2c081de7a0d8729a8c816c9adef67a
2026-08-10 11:17:50 +08:00

400 lines
12 KiB
TypeScript

/**
* @vitest-environment node
*/
import { dbChainMock, queueTableRows, resetDbChainMock, schemaMock } from '@sim/testing'
import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest'
const { mockMaterializeExecutionData } = vi.hoisted(() => ({
mockMaterializeExecutionData: vi.fn(),
}))
vi.mock('@sim/db', () => ({ ...dbChainMock, ...schemaMock }))
vi.mock('@/lib/logs/execution/trace-store', () => ({
materializeExecutionData: mockMaterializeExecutionData,
TRACE_STORE_REF_KEY: 'traceStoreRef',
}))
import {
getExecutionInputForWorkflow,
getExecutionStateForWorkflow,
getLatestExecutionStateWithExecutionId,
getTrustedWorkflowToolExecution,
} from '@/lib/workflows/executor/execution-state'
const EXECUTION_STATE = {
blockStates: {},
executedBlocks: ['block-1'],
blockLogs: [],
decisions: {},
completedLoops: [],
activeExecutionPath: [],
}
describe('execution state lookup', () => {
beforeEach(() => {
vi.clearAllMocks()
resetDbChainMock()
mockMaterializeExecutionData.mockReset()
})
afterAll(() => {
resetDbChainMock()
})
it('materializes externalized execution data for a specific execution', async () => {
const slimExecutionData = {
traceStoreRef: {
__simLargeValueRef: true,
id: 'value-1',
key: 'execution/workspace-1/workflow-1/execution-1/value.json',
kind: 'object',
size: 100,
version: 1,
executionId: 'execution-1',
},
}
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
executionData: slimExecutionData,
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
executionState: EXECUTION_STATE,
})
const result = await getExecutionStateForWorkflow('execution-1', 'workflow-1')
expect(mockMaterializeExecutionData).toHaveBeenCalledWith(slimExecutionData, {
workspaceId: 'workspace-1',
workflowId: 'workflow-1',
executionId: 'execution-1',
})
expect(result).toEqual(EXECUTION_STATE)
})
it('loads a terminal workflow result with an exact persisted Copilot binding', async () => {
const provenance = {
version: 1 as const,
complete: true,
entries: [{ name: 'API_KEY', encryptedValue: 'encrypted-secret' }],
scope: { userId: 'user-1', workspaceId: 'workspace-1' },
}
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
status: 'completed',
executionData: {},
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
correlation: { copilotToolCallId: 'tool-call-1' },
finalOutput: { token: 'raw-secret' },
executionState: { ...EXECUTION_STATE, resolvedSecretTraceProvenance: provenance },
})
await expect(
getTrustedWorkflowToolExecution('execution-1', 'workflow-1', 'tool-call-1')
).resolves.toEqual({
executionId: 'execution-1',
workflowId: 'workflow-1',
status: 'completed',
contentAvailable: true,
finalOutput: { token: 'raw-secret' },
blockLogs: [],
provenance,
})
})
it('accepts a bound complete execution with no activated secrets', async () => {
const provenance = { version: 1 as const, complete: true, entries: [] }
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
status: 'completed',
executionData: {},
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
trigger: { data: { correlation: { copilotToolCallId: 'tool-call-1' } } },
executionState: { ...EXECUTION_STATE, resolvedSecretTraceProvenance: provenance },
})
await expect(
getTrustedWorkflowToolExecution('execution-1', 'workflow-1', 'tool-call-1')
).resolves.toMatchObject({ provenance })
})
it('returns validated incomplete provenance so the terminal projector can fail closed', async () => {
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
status: 'failed',
executionData: {},
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
correlation: { copilotToolCallId: 'tool-call-1' },
executionState: {
...EXECUTION_STATE,
resolvedSecretTraceProvenance: { version: 1, complete: false, entries: [] },
},
})
await expect(
getTrustedWorkflowToolExecution('execution-1', 'workflow-1', 'tool-call-1')
).resolves.toMatchObject({
status: 'failed',
provenance: { version: 1, complete: false, entries: [] },
})
})
it('trusts compacted terminal status while withholding unavailable execution content', async () => {
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
status: 'completed',
executionData: {},
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
correlation: { copilotToolCallId: 'tool-call-1' },
executionStateSummary: {
executedBlockCount: 1,
blockLogCount: 1,
completedLoopCount: 0,
activeExecutionPathLength: 0,
pendingQueueLength: 0,
},
finalOutput: { token: 'must-not-cross' },
})
await expect(
getTrustedWorkflowToolExecution('execution-1', 'workflow-1', 'tool-call-1')
).resolves.toEqual({
executionId: 'execution-1',
workflowId: 'workflow-1',
status: 'completed',
contentAvailable: false,
})
})
it('withholds execution content when persisted provenance is malformed', async () => {
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
status: 'completed',
executionData: {},
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
correlation: { copilotToolCallId: 'tool-call-1' },
finalOutput: { token: 'must-not-cross' },
executionState: {
...EXECUTION_STATE,
resolvedSecretTraceProvenance: { version: 2, complete: true, entries: [] },
},
})
await expect(
getTrustedWorkflowToolExecution('execution-1', 'workflow-1', 'tool-call-1')
).resolves.toEqual({
executionId: 'execution-1',
workflowId: 'workflow-1',
status: 'completed',
contentAvailable: false,
})
})
it('rejects mismatched bindings and nonterminal rows', async () => {
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
status: 'completed',
executionData: {},
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
correlation: { copilotToolCallId: 'another-tool-call' },
executionState: {
...EXECUTION_STATE,
resolvedSecretTraceProvenance: { version: 1, complete: true, entries: [] },
},
})
await expect(
getTrustedWorkflowToolExecution('execution-1', 'workflow-1', 'tool-call-1')
).resolves.toBeNull()
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-2',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
status: 'running',
executionData: {},
},
])
await expect(
getTrustedWorkflowToolExecution('execution-2', 'workflow-1', 'tool-call-1')
).resolves.toBeNull()
})
it('materializes externalized execution data when reusing workflow input', async () => {
const slimExecutionData = {
traceStoreRef: {
__simLargeValueRef: true,
id: 'value-1',
key: 'execution/workspace-1/workflow-1/execution-1/value.json',
kind: 'object',
size: 100,
version: 1,
executionId: 'execution-1',
},
}
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
executionData: slimExecutionData,
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
workflowInput: { leadId: 'lead-1' },
})
const result = await getExecutionInputForWorkflow('execution-1', 'workflow-1')
expect(result).toEqual({
found: true,
input: { leadId: 'lead-1' },
})
expect(mockMaterializeExecutionData).toHaveBeenCalledWith(slimExecutionData, {
workspaceId: 'workspace-1',
workflowId: 'workflow-1',
executionId: 'execution-1',
})
})
it('recovers legacy workflow input from the pre-populated starter block state', async () => {
const legacyInput = { leadId: 'legacy-lead' }
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
executionData: {},
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
executionState: {
blockStates: {
'executed-block': {
output: { leadId: 'wrong-lead' },
executed: true,
executionTime: 10,
},
start: {
output: legacyInput,
executed: false,
executionTime: 0,
},
},
},
})
const result = await getExecutionInputForWorkflow('execution-1', 'workflow-1')
expect(result).toEqual({ found: true, input: legacyInput })
})
it('prefers persisted workflow input over the legacy starter block state', async () => {
const workflowInput = { leadId: 'current-lead' }
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
executionData: {},
},
])
mockMaterializeExecutionData.mockResolvedValueOnce({
workflowInput,
executionState: {
blockStates: {
start: {
output: { leadId: 'legacy-lead' },
executed: false,
executionTime: 0,
},
},
},
})
const result = await getExecutionInputForWorkflow('execution-1', 'workflow-1')
expect(result).toEqual({ found: true, input: workflowInput })
})
it('checks older pointer-backed candidates when the latest has no execution state', async () => {
queueTableRows(schemaMock.workflowExecutionLogs, [
{
executionId: 'execution-2',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
executionState: null,
traceStoreRef: { id: 'value-2' },
},
{
executionId: 'execution-1',
workflowId: 'workflow-1',
workspaceId: 'workspace-1',
executionState: null,
traceStoreRef: { id: 'value-1' },
},
])
mockMaterializeExecutionData
.mockResolvedValueOnce({})
.mockImplementationOnce(async (executionData: Record<string, unknown>) => {
const { traceStoreRef: _traceStoreRef, ...inlineValues } = executionData
return { executionState: EXECUTION_STATE, ...inlineValues }
})
const result = await getLatestExecutionStateWithExecutionId('workflow-1')
expect(result).toEqual({
executionId: 'execution-1',
state: EXECUTION_STATE,
})
expect(mockMaterializeExecutionData).toHaveBeenCalledTimes(2)
expect(mockMaterializeExecutionData).toHaveBeenNthCalledWith(
1,
{
traceStoreRef: { id: 'value-2' },
},
{
workspaceId: 'workspace-1',
workflowId: 'workflow-1',
executionId: 'execution-2',
}
)
})
})