From 5278a47b5558d7f06bb43fc86a786a57ae8ecc48 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Thu, 6 Aug 2026 11:48:36 +0200 Subject: [PATCH] refactor(front): move workflow run step logs into workflow-actions (#23841) Follow-up on unapplied review feedback from #21142. ### Folder structure @thomtrp: > We now have a folder workflow-run/observability, but we have workflow-run related components in workflow-actions folder already. I would avoid that workflow-run/observability folder. The `workflow-run/` folder held nothing but `observability/`, so it is removed entirely and each step log detail component now sits with its action: | File | New location | | --- | --- | | `WorkflowRunStepLogsAiAgentDetail.tsx`, `WorkflowRunStepLogsToolCallRow.tsx` | `workflow-actions/ai-agent-action/components/` | | `WorkflowRunStepLogsCodeDetail.tsx` | `workflow-actions/code-action/components/` | | `WorkflowRunStepLogsHttpRequestDetail.tsx` | `workflow-actions/http-request-action/components/` | | `WorkflowRunStepLogsDetail.tsx`, `WorkflowRunStepLogsEntries.tsx`, `WorkflowRunStepLogsEmailDetail.tsx`, `workflowRunStepLogsStyles.ts` | `workflow-actions/components/` | | `formatDuration.ts`, `formatBytes.ts` | `workflow-actions/utils/` | The email detail stays in the shared `components/` folder since there is no dedicated send-email action folder on the front end (email editing lives at the root as `WorkflowEditActionEmailBase.tsx`). `workflowRunStepLogsStyles.ts` goes next to the shared components rather than `utils/`, since it is styled components and not utils. Also folds in @FelixMalfait's `2 export in 1 file` comment: `workflowRunStepLogsFormatters.ts` is split into `formatDuration.ts` and `formatBytes.ts`. ### AI comments @thomtrp: > same, let's not keep AI comments Removes every comment #21142 introduced, across the front end, server and shared packages: - `WorkflowRunStepLogsEntries.tsx` - the `onlyLatestIteration` prop block - `workflow-run-step-log-schema.ts` - the transport-failure note and the permissive-schema rationale - `strip-ansi-escapes.util.spec.ts`, `build-http-request-step-log.util.spec.ts`, `truncate-string-to-utf8-byte-budget.spec.ts`, `agent-async-executor.service.spec.ts` - the byte-vs-char and pre-fix-behaviour commentary No behaviour change. Locale catalogs are deliberately left untouched; the next i18n run picks up the new source paths. ### Still open from #21142, not covered here - `persistStepLog` try/catch duplicated across the code, tool-backed and ai-agent actions - `draft-email-tool` returning both `sanitizedHtmlBody` and `plainTextBody` - storing both `totalCostInDollars` and `creditsUsedMicro` - the byte-budget truncation utilities being over-engineered - `strip-ansi-escapes` being local to application logs --- .../SidePanelWorkflowRunViewStepContent.tsx | 2 +- .../components}/WorkflowRunStepLogsAiAgentDetail.tsx | 6 +++--- .../components}/WorkflowRunStepLogsToolCallRow.tsx | 0 .../components}/WorkflowRunStepLogsCodeDetail.tsx | 4 ++-- .../components}/WorkflowRunStepLogsDetail.tsx | 10 +++++----- .../components}/WorkflowRunStepLogsEmailDetail.tsx | 8 +++----- .../components}/WorkflowRunStepLogsEntries.tsx | 5 +---- .../components}/workflowRunStepLogsStyles.ts | 0 .../WorkflowRunStepLogsHttpRequestDetail.tsx | 8 +++----- .../workflow-actions/utils/formatBytes.ts} | 8 -------- .../workflow-actions/utils/formatDuration.ts | 7 +++++++ .../application-log/strip-ansi-escapes.util.spec.ts | 4 ---- .../__tests__/agent-async-executor.service.spec.ts | 3 --- .../build-http-request-step-log.util.spec.ts | 11 ----------- .../truncate-string-to-utf8-byte-budget.spec.ts | 5 ----- .../workflow/schemas/workflow-run-step-log-schema.ts | 9 --------- 16 files changed, 25 insertions(+), 65 deletions(-) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability => workflow-steps/workflow-actions/ai-agent-action/components}/WorkflowRunStepLogsAiAgentDetail.tsx (95%) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability => workflow-steps/workflow-actions/ai-agent-action/components}/WorkflowRunStepLogsToolCallRow.tsx (100%) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability => workflow-steps/workflow-actions/code-action/components}/WorkflowRunStepLogsCodeDetail.tsx (94%) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability => workflow-steps/workflow-actions/components}/WorkflowRunStepLogsDetail.tsx (92%) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability => workflow-steps/workflow-actions/components}/WorkflowRunStepLogsEmailDetail.tsx (95%) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability => workflow-steps/workflow-actions/components}/WorkflowRunStepLogsEntries.tsx (91%) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability => workflow-steps/workflow-actions/components}/workflowRunStepLogsStyles.ts (100%) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability => workflow-steps/workflow-actions/http-request-action/components}/WorkflowRunStepLogsHttpRequestDetail.tsx (96%) rename packages/twenty-front/src/modules/workflow/{workflow-run/observability/workflowRunStepLogsFormatters.ts => workflow-steps/workflow-actions/utils/formatBytes.ts} (62%) create mode 100644 packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/utils/formatDuration.ts diff --git a/packages/twenty-front/src/modules/side-panel/pages/workflow/step/view-run/components/SidePanelWorkflowRunViewStepContent.tsx b/packages/twenty-front/src/modules/side-panel/pages/workflow/step/view-run/components/SidePanelWorkflowRunViewStepContent.tsx index 188b9a8870..3879f2645e 100644 --- a/packages/twenty-front/src/modules/side-panel/pages/workflow/step/view-run/components/SidePanelWorkflowRunViewStepContent.tsx +++ b/packages/twenty-front/src/modules/side-panel/pages/workflow/step/view-run/components/SidePanelWorkflowRunViewStepContent.tsx @@ -13,7 +13,7 @@ import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow'; import { getStepDefinitionOrThrow } from '@/workflow/utils/getStepDefinitionOrThrow'; import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState'; -import { WorkflowRunStepLogsDetail } from '@/workflow/workflow-run/observability/WorkflowRunStepLogsDetail'; +import { WorkflowRunStepLogsDetail } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsDetail'; import { WorkflowRunStepInputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepInputDetail'; import { WorkflowRunStepNodeDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepNodeDetail'; import { WorkflowRunStepOutputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepOutputDetail'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsAiAgentDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowRunStepLogsAiAgentDetail.tsx similarity index 95% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsAiAgentDetail.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowRunStepLogsAiAgentDetail.tsx index eadeb25322..a26bdbf27c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsAiAgentDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowRunStepLogsAiAgentDetail.tsx @@ -13,7 +13,7 @@ import { } from 'twenty-ui/icon'; import { themeCssVariables } from 'twenty-ui/theme-constants'; -import { formatDuration } from '@/workflow/workflow-run/observability/workflowRunStepLogsFormatters'; +import { formatDuration } from '@/workflow/workflow-steps/workflow-actions/utils/formatDuration'; import { StyledBadgeGroup, StyledEmptyHint, @@ -27,8 +27,8 @@ import { StyledSummaryCard, StyledSummaryHeader, StyledTitle, -} from '@/workflow/workflow-run/observability/workflowRunStepLogsStyles'; -import { WorkflowRunStepLogsToolCallRow } from '@/workflow/workflow-run/observability/WorkflowRunStepLogsToolCallRow'; +} from '@/workflow/workflow-steps/workflow-actions/components/workflowRunStepLogsStyles'; +import { WorkflowRunStepLogsToolCallRow } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowRunStepLogsToolCallRow'; import { formatNumber } from '~/utils/format/formatNumber'; const StyledModelBadge = styled.span` diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsToolCallRow.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowRunStepLogsToolCallRow.tsx similarity index 100% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsToolCallRow.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowRunStepLogsToolCallRow.tsx diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsCodeDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowRunStepLogsCodeDetail.tsx similarity index 94% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsCodeDetail.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowRunStepLogsCodeDetail.tsx index c0c99f86cd..ea7d2588c2 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsCodeDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowRunStepLogsCodeDetail.tsx @@ -11,7 +11,7 @@ import { import { themeCssVariables } from 'twenty-ui/theme-constants'; import { MONOSPACE_FONT_FAMILY } from '@/ui/theme/constants/MonospaceFontFamily'; -import { formatDuration } from '@/workflow/workflow-run/observability/workflowRunStepLogsFormatters'; +import { formatDuration } from '@/workflow/workflow-steps/workflow-actions/utils/formatDuration'; import { StyledErrorCard, StyledErrorMessageText, @@ -26,7 +26,7 @@ import { StyledSummaryCard, StyledSummaryHeader, StyledTitle, -} from '@/workflow/workflow-run/observability/workflowRunStepLogsStyles'; +} from '@/workflow/workflow-steps/workflow-actions/components/workflowRunStepLogsStyles'; const StyledErrorHeader = styled.div` align-items: center; diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsDetail.tsx similarity index 92% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsDetail.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsDetail.tsx index c88eea2003..f995f8282f 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsDetail.tsx @@ -10,11 +10,11 @@ import { type JsonValue } from 'type-fest'; import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow'; import { useWorkflowRunStepLog } from '@/workflow/hooks/useWorkflowRunStepLog'; -import { WorkflowRunStepLogsAiAgentDetail } from '@/workflow/workflow-run/observability/WorkflowRunStepLogsAiAgentDetail'; -import { WorkflowRunStepLogsCodeDetail } from '@/workflow/workflow-run/observability/WorkflowRunStepLogsCodeDetail'; -import { WorkflowRunStepLogsEmailDetail } from '@/workflow/workflow-run/observability/WorkflowRunStepLogsEmailDetail'; -import { WorkflowRunStepLogsEntries } from '@/workflow/workflow-run/observability/WorkflowRunStepLogsEntries'; -import { WorkflowRunStepLogsHttpRequestDetail } from '@/workflow/workflow-run/observability/WorkflowRunStepLogsHttpRequestDetail'; +import { WorkflowRunStepLogsAiAgentDetail } from '@/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowRunStepLogsAiAgentDetail'; +import { WorkflowRunStepLogsCodeDetail } from '@/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowRunStepLogsCodeDetail'; +import { WorkflowRunStepLogsEmailDetail } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsEmailDetail'; +import { WorkflowRunStepLogsEntries } from '@/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsEntries'; +import { WorkflowRunStepLogsHttpRequestDetail } from '@/workflow/workflow-steps/workflow-actions/http-request-action/components/WorkflowRunStepLogsHttpRequestDetail'; import { getIsDescendantOfIterator } from '@/workflow/workflow-steps/utils/getIsDescendantOfIterator'; import { useCopyToClipboard } from '~/hooks/useCopyToClipboard'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsEmailDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsEmailDetail.tsx similarity index 95% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsEmailDetail.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsEmailDetail.tsx index 4932cd940b..44dc0605d6 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsEmailDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsEmailDetail.tsx @@ -11,10 +11,8 @@ import { } from 'twenty-ui/icon'; import { themeCssVariables } from 'twenty-ui/theme-constants'; -import { - formatBytes, - formatDuration, -} from '@/workflow/workflow-run/observability/workflowRunStepLogsFormatters'; +import { formatBytes } from '@/workflow/workflow-steps/workflow-actions/utils/formatBytes'; +import { formatDuration } from '@/workflow/workflow-steps/workflow-actions/utils/formatDuration'; import { StyledBadgeGroup, StyledBodyMeta, @@ -32,7 +30,7 @@ import { StyledSummaryCard, StyledSummaryHeader, StyledTitle, -} from '@/workflow/workflow-run/observability/workflowRunStepLogsStyles'; +} from '@/workflow/workflow-steps/workflow-actions/components/workflowRunStepLogsStyles'; const StyledModeBadge = styled.span` background: ${themeCssVariables.background.transparent.light}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsEntries.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsEntries.tsx similarity index 91% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsEntries.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsEntries.tsx index 75dde21b1b..236ceda4b7 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsEntries.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowRunStepLogsEntries.tsx @@ -7,7 +7,7 @@ import { MONOSPACE_FONT_FAMILY } from '@/ui/theme/constants/MonospaceFontFamily' import { StyledSection, StyledSectionTitle, -} from '@/workflow/workflow-run/observability/workflowRunStepLogsStyles'; +} from '@/workflow/workflow-steps/workflow-actions/components/workflowRunStepLogsStyles'; const StyledEntriesList = styled.div` background: ${themeCssVariables.background.tertiary}; @@ -77,9 +77,6 @@ export const WorkflowRunStepLogsEntries = ({ onlyLatestIteration = false, }: { entries: WorkflowRunStepLog['entries']; - // Set when the parent step lives inside an iterator loop: each iteration - // overwrites the same `stepLogs[stepId]` key, so what we render here is - // only the latest iteration's entries — not a cumulative view. onlyLatestIteration?: boolean; }) => { const { t } = useLingui(); diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/workflowRunStepLogsStyles.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/workflowRunStepLogsStyles.ts similarity index 100% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/workflowRunStepLogsStyles.ts rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/workflowRunStepLogsStyles.ts diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsHttpRequestDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/http-request-action/components/WorkflowRunStepLogsHttpRequestDetail.tsx similarity index 96% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsHttpRequestDetail.tsx rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/http-request-action/components/WorkflowRunStepLogsHttpRequestDetail.tsx index 67be6e963e..ba0a33f941 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-run/observability/WorkflowRunStepLogsHttpRequestDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/http-request-action/components/WorkflowRunStepLogsHttpRequestDetail.tsx @@ -13,10 +13,8 @@ import { import { themeCssVariables } from 'twenty-ui/theme-constants'; import { MONOSPACE_FONT_FAMILY } from '@/ui/theme/constants/MonospaceFontFamily'; -import { - formatBytes, - formatDuration, -} from '@/workflow/workflow-run/observability/workflowRunStepLogsFormatters'; +import { formatBytes } from '@/workflow/workflow-steps/workflow-actions/utils/formatBytes'; +import { formatDuration } from '@/workflow/workflow-steps/workflow-actions/utils/formatDuration'; import { StyledBadgeGroup, StyledBodyMeta, @@ -34,7 +32,7 @@ import { StyledSummaryCard, StyledSummaryHeader, StyledTitle, -} from '@/workflow/workflow-run/observability/workflowRunStepLogsStyles'; +} from '@/workflow/workflow-steps/workflow-actions/components/workflowRunStepLogsStyles'; const StyledMethodBadge = styled.span<{ method: string }>` background: ${themeCssVariables.background.transparent.light}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-run/observability/workflowRunStepLogsFormatters.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/utils/formatBytes.ts similarity index 62% rename from packages/twenty-front/src/modules/workflow/workflow-run/observability/workflowRunStepLogsFormatters.ts rename to packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/utils/formatBytes.ts index 84d831a0c8..a3b8bf5d70 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-run/observability/workflowRunStepLogsFormatters.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/utils/formatBytes.ts @@ -1,11 +1,3 @@ -export const formatDuration = (ms: number): string => { - if (ms < 1000) { - return `${ms}ms`; - } - - return `${(ms / 1000).toFixed(1)}s`; -}; - export const formatBytes = (bytes: number): string => { if (bytes < 1024) { return `${bytes} B`; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/utils/formatDuration.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/utils/formatDuration.ts new file mode 100644 index 0000000000..baaae9592d --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/utils/formatDuration.ts @@ -0,0 +1,7 @@ +export const formatDuration = (ms: number): string => { + if (ms < 1000) { + return `${ms}ms`; + } + + return `${(ms / 1000).toFixed(1)}s`; +}; diff --git a/packages/twenty-server/src/engine/core-modules/event-logs/producers/application-log/strip-ansi-escapes.util.spec.ts b/packages/twenty-server/src/engine/core-modules/event-logs/producers/application-log/strip-ansi-escapes.util.spec.ts index 5c4fc2c936..fa2a70bee2 100644 --- a/packages/twenty-server/src/engine/core-modules/event-logs/producers/application-log/strip-ansi-escapes.util.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/event-logs/producers/application-log/strip-ansi-escapes.util.spec.ts @@ -6,7 +6,6 @@ describe('stripAnsiEscapes', () => { }); it('strips SGR color codes from a yellow value', () => { - // What `console.log(chalk.yellow('4 '))` emits. expect(stripAnsiEscapes('\u001B[33m4 \u001B[39m')).toBe('4 '); }); @@ -40,9 +39,6 @@ describe('stripAnsiEscapes', () => { }); it('leaves untouched the bracket text that survived a missing ESC', () => { - // Defensive: if the ESC byte was already stripped upstream, we should not - // try to "fix" the bracketed remnants (we cannot tell them apart from real - // user text). expect(stripAnsiEscapes('[33m4 [39m')).toBe('[33m4 [39m'); }); }); diff --git a/packages/twenty-server/src/engine/metadata-modules/ai/ai-agent-execution/services/__tests__/agent-async-executor.service.spec.ts b/packages/twenty-server/src/engine/metadata-modules/ai/ai-agent-execution/services/__tests__/agent-async-executor.service.spec.ts index c0c21f187a..1937dee05a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/ai/ai-agent-execution/services/__tests__/agent-async-executor.service.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/ai/ai-agent-execution/services/__tests__/agent-async-executor.service.spec.ts @@ -348,7 +348,6 @@ describe('AgentAsyncExecutorService — workflow agent role-scoped tool resoluti expect(result.nativeWebSearchCallCount).toBe(0); expect(result.totalCostInDollars).toBeCloseTo(0.0042, 6); - // credits = dollars * 1_000_000 expect(result.creditsUsedMicro).toBe(4200); }); @@ -369,8 +368,6 @@ describe('AgentAsyncExecutorService — workflow agent role-scoped tool resoluti ], usage: { ...baseUsage, - // inputTokens (100) is the full prompt: noCache(60) + cacheRead(10) + - // cacheCreation(30) — the emitted total must not add the 30 again inputTokenDetails: { noCacheTokens: 60, cacheReadTokens: 10, diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/http-request/utils/__tests__/build-http-request-step-log.util.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/http-request/utils/__tests__/build-http-request-step-log.util.spec.ts index ed270ce62d..b10ee5f310 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/http-request/utils/__tests__/build-http-request-step-log.util.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/http-request/utils/__tests__/build-http-request-step-log.util.spec.ts @@ -85,12 +85,6 @@ describe('buildHttpRequestStepLog', () => { }); it('truncates non-ASCII bodies by UTF-8 bytes, not UTF-16 code units', () => { - // CJK characters take 3 UTF-8 bytes each but 1 UTF-16 code unit. - // Before the byte-aware fix, `redacted.slice(0, 32_000)` on this payload - // would emit ~96 KB of UTF-8 (three times the intended cap). After the - // fix the truncated payload stays within the cap, plus at most one - // U+FFFD replacement char (~3 bytes) for a multi-byte sequence cut at - // the boundary. const longCjkPayload = '日'.repeat(40_000); const stepLog = buildHttpRequestStepLog({ @@ -197,9 +191,6 @@ describe('buildHttpRequestStepLog', () => { }); it('redacts sensitive query params even when the URL is unparseable (regression)', () => { - // Whitespace in the host trips up the WHATWG URL parser, so this URL - // is rejected by `new URL()`. Before the fallback was added, the catch - // branch returned the raw URL with secrets intact. const unparseableUrl = 'https://api example.com/data?page=1&api_key=AKIA-leaked&token=oauth-leaked&safe=ok'; @@ -226,8 +217,6 @@ describe('buildHttpRequestStepLog', () => { }); it('redacts percent-encoded sensitive param names in unparseable URLs', () => { - // `api%5Fkey` decodes to `api_key` — the fallback must decode before - // matching against the sensitive-name set. const unparseableUrl = 'https://api example.com/x?api%5Fkey=leaked'; expect(() => new URL(unparseableUrl)).toThrow(); diff --git a/packages/twenty-server/src/utils/__test__/truncate-string-to-utf8-byte-budget.spec.ts b/packages/twenty-server/src/utils/__test__/truncate-string-to-utf8-byte-budget.spec.ts index 1960ee453e..f43b4ad744 100644 --- a/packages/twenty-server/src/utils/__test__/truncate-string-to-utf8-byte-budget.spec.ts +++ b/packages/twenty-server/src/utils/__test__/truncate-string-to-utf8-byte-budget.spec.ts @@ -40,7 +40,6 @@ describe('truncateStringToUtf8ByteBudget', () => { }); it('reports originalBytes in UTF-8 bytes for non-ASCII content', () => { - // 1 × '日' = 3 UTF-8 bytes but only 1 UTF-16 code unit. const result = truncateStringToUtf8ByteBudget('日'.repeat(1_000), 30); expect(result.originalBytes).toBe(3_000); @@ -48,8 +47,6 @@ describe('truncateStringToUtf8ByteBudget', () => { }); it('truncates CJK content within budget rather than 3× over (regression)', () => { - // Pre-fix `slice(0, maxBytes)` would have emitted 32_000 chars = - // ~96_000 bytes. The byte-aware util must stay close to the cap. const cjk = '日'.repeat(40_000); const cap = 32_000; @@ -59,8 +56,6 @@ describe('truncateStringToUtf8ByteBudget', () => { result.value.replace(TRUNCATION_SENTINEL, ''), ); - // Allow at most a single U+FFFD substitution (3 UTF-8 bytes) when the - // byte boundary falls inside a multi-byte sequence. expect(truncatedPayloadBytes).toBeLessThanOrEqual(cap + 3); expect(truncatedPayloadBytes).toBeGreaterThan(cap - 3); }); diff --git a/packages/twenty-shared/src/workflow/schemas/workflow-run-step-log-schema.ts b/packages/twenty-shared/src/workflow/schemas/workflow-run-step-log-schema.ts index 9b2f89f775..1d6dffd39b 100644 --- a/packages/twenty-shared/src/workflow/schemas/workflow-run-step-log-schema.ts +++ b/packages/twenty-shared/src/workflow/schemas/workflow-run-step-log-schema.ts @@ -60,8 +60,6 @@ const httpRequestStepLogDetailsSchema = z.object({ bodyBytes: z.number().optional(), bodyTruncated: z.boolean().optional(), }), - // `response` is absent for transport-level failures (DNS, timeout, TLS, - // etc.) — only `error` is set in that case. response: z .object({ status: z.number(), @@ -130,11 +128,4 @@ export const workflowRunStepLogSchema = z.object({ sizeBytes: z.number(), }); -// We intentionally keep the runtime schema permissive: the column is a -// JSONB blob written by the server and the consumers don't validate -// individual `details` shapes. The strict per-step type (with the -// discriminated `details` union) lives in `WorkflowRunStepLog` and is -// applied at the boundaries that *produce* logs (server-side writers). -// Tighter zod parsing here would collapse the discriminated union to `{}` -// when inferred through `z.record`, breaking front-end indexing. export const workflowRunStepLogsSchema = z.record(z.string(), z.unknown());