v0.7.57: forking webhook URL, markdown editor overflow, fix ui improvements - #6287
Conversation
* refactor(logs): centralize workflow-id resolution and editor path The logs list, its context menu, and the details panel each resolved a log's workflow id with their own copy of `workflow?.id || workflowId`, and the list disagreed with the details panel on what counts as a deleted workflow. Extract `resolveLogWorkflowId` and `workflowEditorPath` so the three surfaces cannot drift. `resolveLogWorkflowId` also returns null for Sim agent jobs, which have no workflow of their own. Only the context menu's "Open Workflow" item adopts that stricter predicate; cancel and retry keep using the previous `hasWorkflow` check so their gating is unchanged. * feat(logs): open the workflow from the log details panel The workflow name in a log's details panel was static text, so the only way to reach the workflow was the row's right-click context menu. Make the label a link to the workflow editor, opening in a new tab so the log list keeps its filters, scroll position, and open panel. On hover or keyboard focus the leading workflow icon morphs into SquareArrowUpRight, reusing the grid-stacked cross-fade already used by the resource header breadcrumb. Sim agent jobs and deleted workflows have no reachable workflow and stay static text. Adds a `group-hover-hover` variant so the morph is gated on a real hover-capable pointer, matching the existing `hover-hover` variant and keeping touch devices out of a half-applied hover state. * refactor(logs): use the existing group-hover variant for the workflow link Drops the group-hover-hover Tailwind variant this branch added and moves the details-panel workflow link to plain group-hover:, matching the variant already used throughout the app. tailwind.config.ts is untouched by the branch again; all colors, radii, and the focus ring come from existing design tokens.
…reject a failed generation (#6283) * fix(providers): name the failing phase of a stalled OpenAI call, and reject a failed generation An agent block hung ~4.5 minutes with an empty trace and surfaced only the runtime's own `TimeoutError: The operation timed out.` The cause was a runaway generation: the model repeated one tool call until it consumed the whole 128,000-token output budget, which takes minutes, and `/v1/responses` withholds its 200 until generation finishes — so the client waited, bounded only by an undocumented runtime socket deadline, and gave up before the response existed. Nothing in the trace could distinguish that from a request the provider never answered, or from one whose body never arrived. - Name the phase a transport failure died in — `awaiting-response-headers` vs `reading-response-body` — with status, ttfb, content-length and `x-request-id`. undici draws the same line as two error types (UND_ERR_HEADERS_TIMEOUT / UND_ERR_BODY_TIMEOUT); the OpenAI SDK captures `x-request-id` for the same reason. It rides the error message because that reaches the trace span, which survives when a task stops shipping logs. - Carry the cause through `ProviderError` so a transport timeout still classifies after wrapping overwrites `name`. - Reject a 200 that reports a failed or unusable generation instead of returning empty content with billed tokens, and stop truncated tool calls from executing. Matches `streamResponsesTurn`, which already did this, and `@ai-sdk/openai`, which throws on the same condition. - Bound non-JSON error bodies so a gateway error page cannot become the user-facing block error. Deliberately not included: a response-body deadline (the observed failure is in the headers phase, and the body transfers in ~1ms) and status-based retries (worth doing, unrelated to this, and separable). * test(providers): pin that a structured provider error survives the error-body bound * chore(providers): trim comments to the non-obvious why * fix(providers): let a deadline while reading an error body propagate * fix(providers): name the body phase when an error body read fails
…ping to the editor (#6285)
* improvement(forking): make webhook url mapping clear * fix(forking): honour drops before the unmapped gate, match provider on URL adoption Review round 1 on #6272. - Drop was inert for required references: `postCopyUnmappedRequired` gates before the cleared-ref gate that honours acknowledgments, so a source-deleted reference on a required field still failed with "map all required ... first". Verified drops are now resolved once (`verifyForkDropAcknowledgments`) and subtracted from both gates. Verification is not optional: an unmapped reference of a non-blocking kind (credential, env-var) never re-blocks downstream, so subtracting raw acknowledgments would let a crafted payload skip the required gate. - URL adoption now requires provider equality. A count-only 1:1 pairing could hand a GitHub URL to an arriving Slack trigger, keeping the endpoint alive while every request failed signature verification - and reporting the URL as preserved. - `resolveTriggerId` moved from `lib/webhooks/deploy.ts` to `@/triggers/webhook-url` so the deploy path and the fork's provider check share one resolution. - Trigger URL warnings render the full public URL in the heads-up section and name the URL in the overwrite confirm, where identical workflow names were ambiguous. - The Drop control renders once per resource and states how many fields it covers; the remapper clears by reference, so a per-row control implied a choice the write path cannot honour. - Export clears `workflow-selector`: nothing on the import path remaps workflow ids (`import-export.ts` re-creates each workflow under a fresh id), so a preserved reference dangled - bundle or not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryHigh Risk Overview Logs add a shared Wand strips markdown code fences from completed generations (including Smaller UX fixes: global Reviewed by Cursor Bugbot for commit 2d90c72. Configure here. |
Greptile SummaryThe PR combines workflow-forking URL reconciliation, log-to-workflow navigation, OpenAI transport diagnostics, markdown editor and Wand fixes, and shared UI typography improvements.
Confidence Score: 5/5The PR appears safe to merge, with only non-blocking previously reported issues remaining. The remaining issues concern incomplete timeout diagnostics and repository documentation/import conventions; no blocking failure remains. Files Needing Attention: apps/sim/providers/openai/core.ts, apps/sim/app/api/workspaces/[id]/fork/diff/route.ts, apps/sim/ee/workspace-forking/components/fork-sync/fork-sync-view.tsx, apps/sim/app/workspace/[workspaceId]/logs/utils.test.ts
|
| Filename | Overview |
|---|---|
| apps/sim/providers/openai/core.ts | Adds transport-phase annotation and stricter failed-response handling for OpenAI requests. |
| apps/sim/ee/workspace-forking/lib/promote/trigger-urls.ts | Computes promoted webhook trigger URLs from the selected workflow and deployment mappings. |
| apps/sim/ee/workspace-forking/components/fork-sync/trigger-choices.ts | Models user-selectable trigger deployment choices for fork synchronization. |
| apps/sim/app/workspace/[workspaceId]/logs/components/log-details/log-details.tsx | Adds workflow-opening behavior to the log details surface. |
| apps/sim/lib/wand/strip-code-fences.ts | Normalizes Wand-generated code by removing surrounding markdown fences. |
Reviews (2): Last reviewed commit: "fix(wand): stop markdown code fences lan..." | Re-trigger Greptile
…picks (#6290) Two Cursor findings on #6272, both in the preview layer - the sync's write path was correct in each case, but the UI stated an outcome that did not match it. - The heads-up and overwrite confirm read `triggerUrlChanges` straight off the diff, which the server computes with its DEFAULT resolution before the user chooses anything. Selecting "Generate new URL" for a trigger that would have adopted a URL therefore killed that URL with no warning, in the one modal whose job is to state irreversible consequences (it also over-warned in the reverse case). The diff now returns the RAW retiring set and the client subtracts the live choices, so the rows, the heads-up and the confirm cannot disagree. - The picker let two triggers select the same retiring URL and showed both as keeping it. Two blocks cannot serve one path (`path_deployment_unique`) and the resolver awards it to the first slot, so the loser silently got a new URL. A path another row claimed is now disabled and named, and each row displays its RESOLVED outcome rather than its raw pick. The choice resolution is a pure module mirroring `resolveForkTriggerPaths` (offered-paths guard, first-claim-wins), so the preview and the server agree by construction rather than by two hand-kept implementations. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ht (#6291) * improvement(emcn): let every primitive inherit the document font weight #6241 flattened the type scale by deleting the tailwind `fontWeight` override that remapped `font-medium` to 440/480. Nothing was restyled, but the utility's meaning changed: every one of ~505 call sites written when `font-medium` sat ~10 units above body snapped to a stock 500 against a body that also dropped 430 -> 400. The tab strip and table header Emir reported are two symptoms. The same PR added the "Font Weight" section to sim-styling.md declaring the end state (400 default, weight class only to step up) without migrating the codebase to it, so the rule and its violations shipped together and no gate could flag it. Removes the hardcoded weight from the ~20 pre-chip emcn primitives so they inherit 400, matching the chip family that was already correct. Deletes the three `font-normal` overrides that existed only to undo those defaults (`TabStrip`, `ChipCombobox`, `ChipModalField`) — their TSDoc said as much. `<th>` needed care in the other direction: Preflight resets h1-h6 but not `th`, so a header keeps the UA bold 700 and `font-medium` was holding it *down*. Deleting it made headers heavier. Rather than neutralize per call site — the codebase had already accumulated 12 such workarounds — globals.css completes Preflight with `th { font-weight: inherit }`, and the 8 now-dead `font-normal` workarounds come out. The rule keeps no element-level exceptions. Two width-measurement mirrors had to move with the text they measure: table-grid's auto-fit canvas and tag-input's hidden sizing span. Left stale, both would mis-measure. Also: drops an inline `font-weight:500` from the header drag ghost, normalizes `text-[13px]`/`text-[11px]` to `text-small`/`text-xs`, aligns the landing table previews that clone the product header, documents AvatarFallback's deliberate step-up, and corrects the stale AGENTS.md line claiming Button owns a weight. Verified: typecheck 0, lint clean, full vitest run identical to origin/staging across three runs (158 failed suites / 1 failed test / 16350 passing — all pre-existing: a PostCSS env error and a missing `rg` binary). * fix(tables): align the workflow-group drag ghost with the label it previews Cursor Bugbot caught the sibling of the ghost fixed in column-header-menu: this one kept an inline `font-weight:500` after the band label dropped to the inherited 400, so the drag preview no longer matched the text it represents — the same mirror drift this PR fixes for the width-measurement spans. It was drifted on size too: hardcoded `font-size:13px` against a label that is `text-xs` (11px), so it never matched. Both now come from the token the label uses, which also clears the inline fontWeight the styling rule bans. * fix(toolbar): stop the block drag preview hardcoding a weight its label does not use Third instance of the same mirror drift, found by sweeping rather than waiting for it to be reported. The toolbar item label renders at the inherited 400 (its container is `chipVariants`, which is weight-free), but the drag preview hardcoded `font-weight: 500` — so the preview never matched the item it previews, before or after this PR. Drops the weight only. The 16px is left alone: a drag preview reading larger than its source is a deliberate affordance, not a mismatch. Not fixed here, deliberately: the `font-weight: 500` in code-editor.tsx's highlight layer. That HTML is rendered in registration with a transparent textarea, so weight affects glyph advance widths and the caret alignment — it needs live in-editor verification, unlike a detached drag ghost. Its two placeholder branches already disagree on weight, so it wants its own change. * revert(canvas): drop the workflow-editor panel changes from this PR The canvas panel is under active modification elsewhere, so this PR stays out of it. Reverts the toolbar search input, the sub-block table cell and its overlay mirror, the messages-input textarea and its mirror, and the block drag preview — all back to staging verbatim. Cursor Bugbot was right about that last one and I was wrong: the preview mirrors the drag DESTINATION (its TSDoc says "looks like a workflow block", and 250px/16px are block-card dimensions), not the toolbar chip I had compared it against. workflow-block-view renders the title `font-medium text-md`, so its 500 was correct. Moot now that the file is reverted, but worth recording so the next sweep does not repeat the mistake. The globals `th` rule still covers the sub-block table header without a call-site class; the explicit font-medium there simply wins over it, exactly as staging renders today.
* fix(wand): stop markdown code fences landing in generated code Strip fences from wand output for raw-value generation types, reset the conversation history when a Function block switches language, and give the Python prompt the worked example the JavaScript one already had. * fix(wand): preserve nested fences and retire stale history on reset Slice only the outermost fence delimiters so a fenced body containing line-leading backticks keeps every interior line, and skip the history append when a language reset retired the request mid-flight. * refactor(wand): drop unreachable guard in fence stripper The trimStart check made the -1 branch dead and stated "opens with a fence" twice. Derive it once from the first fence line's position. * chore(wand): remove unused onGenerationComplete callback No call site ever passed it, so the branch never ran. The props interface makes the removal compile-time verified. * fix(wand): never treat an interior fence line as the closer A truncated response whose body embeds line-leading backticks lost every line after the first embedded delimiter. Only the opening line and a final fence line are removed now. Sync the history epoch in a layout effect so a request settling before the passive flush cannot append to already-reset history. * test(wand): record the trailing-fence ambiguity as a decision A bare fence on the last line closes the wrapper in every well-formed response and is content only when generation stopped exactly on an embedded delimiter. Nothing separates the two, so assert the chosen behavior instead of leaving it implicit.
|
@cursor review |
* feat(copilot): attribute Sim tool calls to agents * fix(review): bound agent metric labels * feat(copilot): attribute tool latency to agents * feat(copilot): attribute tool spans to agents * refactor(copilot): simplify tool attribute naming * fix(copilot): bound tool span agent labels
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2d90c72. Configure here.
Uh oh!
There was an error while loading. Please reload this page.