Commit Graph

4297 Commits

Author SHA1 Message Date
Waleed Latif
55f55ff900 fix(layout): render PublicEnvScript as plain inline <script>
next-runtime-env's <PublicEnvScript /> uses next/script beforeInteractive
internally. On Next.js error-page shells (<html id="__next_error__">),
beforeInteractive is not honored — the env script is serialized into the
RSC stream instead of being hoisted as a real <script> in <head>, so it
runs after client chunks evaluate. Any module that calls getBaseUrl()
at module-eval time (e.g. lib/auth/auth-client.ts) then crashes because
window['__ENV'] is still undefined.

disableNextScript renders a plain inline <script> in <head> that the
browser executes synchronously during HTML parse on every render path,
including error pages. Fixes "Application error: a client-side exception"
on 404 routes like /models/anthropic/xxx and /integrations/rand.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 11:45:15 -07:00
Waleed Latif
8ad41a2e2b fix(landing): render proper 404 for invalid /models and /integrations routes 2026-04-18 21:10:10 -07:00
Waleed
f91c1b614a chore(docker): add packages/utils to app and realtime Dockerfiles (#4229)
* chore(docker): add packages/utils to app and realtime Dockerfiles

* chore(docker): copy packages/utils in realtime runner stage
2026-04-18 18:00:44 -07:00
Waleed
b5674d9ed4 improvement(codebase): centralize test mocks, extract @sim/utils, remove dead code (#4228)
* improvement(codebase): centralize test mocks, extract @sim/utils, remove dead code

* improvement(codebase): apply @sim/utils conventions to staging-introduced files
2026-04-18 14:39:03 -07:00
Theodore Li
c19187257e fix(ui): stop scrolling on leaving workflow sidebar for drag-drop (#4139)
* fix(ui): stop scrolling on leaving workflow sidebar for drag-drop

* Address comments, fix hover state

* address comments
2026-04-18 15:45:25 -04:00
Vikhyath Mondreti
c246f5c660 improvement(billing): route scope by subscription referenceId, sync plan from Stripe, transfer storage on org join, outbox service (#4219)
* fix(billing): route scope by subscription referenceId, sync plan from Stripe, transfer storage on org join

Route every billing decision (usage limits, credits, storage, rate
limit, threshold billing, webhooks, UI permissions) through the
subscription's `referenceId` instead of plan-name heuristics. Fixes
the production state where a `pro_6000` subscription attached to an
organization was treated as personal Pro by display/edit code while
execution correctly enforced the org cap.

Scope
- Add `isOrgScopedSubscription(sub, userId)` (pure) and
  `isSubscriptionOrgScoped(sub)` (async DB-backed) helpers. One is
  used wherever a user perspective is available; the other in webhook
  handlers that only have a subscription row.
- Replace plan-name scope checks in ~20 files: usage/limit readers,
  credits balance + purchase, threshold billing, storage limits +
  tracking, rate limiter, invoice + subscription webhooks, seat
  management, membership join/leave, `switch-plan` admin gate,
  admin credits/billing routes, copilot 402 handler, UI subscription
  settings + permissions + sidebar indicator, React Query types.

Plan sync
- Add `syncSubscriptionPlan(subscriptionId, currentPlan, planFromStripe)`
  called from `onSubscriptionComplete` and `onSubscriptionUpdate` so
  the DB `plan` column heals on every Stripe event. Pro->Team upgrades
  previously updated price, seats, and referenceId but left `plan`
  stale — this is what produced the `pro_6000`-on-org row.

Priority + grace period
- `getHighestPrioritySubscription` now prefers org over personal
  within each tier (Enterprise > Team > Pro, org > personal at each).
  A user with a `cancelAtPeriodEnd` personal Pro who joins a paid org
  routes pooled resources to the org through the grace window.
- `calculateSubscriptionOverage` personal-Pro branch reads user_stats
  directly (bypassing priority) and bills only `proPeriodCostSnapshot`
  when the user joined a paid org mid-cycle, so post-join org usage
  isn't double-charged on the personal Pro's final invoice.
  `resetUsageForSubscription` mirrors this: preserves
  `currentPeriodCost` / `currentPeriodCopilotCost` when
  `proPeriodCostSnapshot > 0` so the org's next cycle-close captures
  post-join usage correctly.

Uniform base-price formula
- `basePrice × (seats ?? 1)` everywhere: `getOrgUsageLimit`,
  `updateOrganizationUsageLimit`, `setUsageLimitForCredits`,
  `calculateSubscriptionOverage`, threshold billing,
  `syncSubscriptionUsageLimits`, `getOrganizationBillingData`.
  Admin dashboard math now agrees with enforcement math.

Storage transfer on join
- Invitation-accept flow moves `user_stats.storageUsedBytes` into
  `organization.storageUsedBytes` inside the same transaction when
  the org is paid.
- `syncSubscriptionUsageLimits` runs a bulk-backfill version so
  members who joined before this fix, or orgs that upgraded from
  free to paid after members joined, get pulled into the org pool
  on the next subscription event. Idempotent.

UX polish
- Copilot 402 handler differentiates personal-scoped ("increase your
  usage limit") from org-scoped ("ask an owner or admin to raise the
  limit") while keeping the `increase_limit` action code the parser
  already understands.
- Duplicate-subscription error on team upgrade names the existing
  plan via `getDisplayPlanName`.
- Invitation-accept invalidates subscription + organization React
  Query caches before redirect so settings doesn't flash the user's
  pre-join personal view.

Dead code removal
- Remove unused `calculateUserOverage`, and the following fields on
  `SubscriptionBillingData` / `getSimplifiedBillingSummary` that no
  consumer in the monorepo read: `basePrice`, `overageAmount`,
  `totalProjected`, `tierCredits`, `basePriceCredits`,
  `currentUsageCredits`, `overageAmountCredits`, `totalProjectedCredits`,
  `usageLimitCredits`, `currentCredits`, `limitCredits`,
  `lastPeriodCostCredits`, `lastPeriodCopilotCostCredits`,
  `copilotCostCredits`, and the `organizationData` subobject. Add
  `metadata: unknown` to match what the server returns.

Notes for the triggering customer
- The `pro_6000`-on-org row self-heals on the next Stripe event via
  `syncSubscriptionPlan`. For the one known customer, a direct
  UPDATE is sufficient:
  `UPDATE subscription SET plan='team_6000' WHERE id='aq2...' AND plan='pro_6000'`.

Made-with: Cursor

* fix tests

* address more comments

* progress

* harden further

* outbox service

* address comments

* address comment on check

* simplify

* cleanup code

* minor improvement
2026-04-18 10:46:14 -07:00
Waleed
28b4c4cc67 fix(blocks): resolve variable display in mothership resource preview (#4226)
* fix(blocks): resolve variable display in mothership resource preview

Variables block showed empty assignments in the embedded workflow preview
because currentWorkflowId was read from URL params, which don't contain
workflowId in the mothership route. Fall back to activeWorkflowId from
the workflow registry.

* fix(blocks): narrow currentWorkflowId to string to satisfy strict null checks
2026-04-18 10:26:46 -07:00
Vikhyath Mondreti
32541e79d4 chore(readme): update tech stack section (#4227)
* chore(readme): update tech stack section

* fix
2026-04-18 10:02:54 -07:00
Waleed
a01f80c6a3 feat(tables): column selection, keyboard shortcuts, drag reorder, and undo improvements (#4222)
* feat(tables): add column selection, missing keyboard shortcuts, and Sheets-aligned operations

Click column headers to select entire columns, shift-click to extend to
a column range. Delete, cut, and copy operations work on column
selections with full undo/redo support. Adds Home, End, Ctrl+Home,
Ctrl+End, PageUp, PageDown, Ctrl+Space, and all Shift variants.
Changes Ctrl+A to select all cells instead of checkbox rows. Column
header dropdown menu now opens on right-click instead of left-click.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): chevron opens dropdown, drag header to reorder columns

Split column header into label area (click to select, draggable for
reorder) and chevron button (click to open dropdown menu). Remove
the grip handle — dragging the header itself now reorders columns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): full-column highlight during drag reorder

Replace the thin 2px line drop indicator with a full-column highlight
that spans the entire table height, matching Google Sheets behavior.
The insertion line is still shown at the drop edge for precision.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): handle drag reorder edge cases, dim source column

Suppress drop indicator when drag would result in no position change
(dragging onto self or adjacent no-op positions). Dim the source
column body cells during drag with a background overlay. Skip the
API call when the computed order is identical to the current order.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(tables): add column reorder undo/redo, body drop targets, and escape cancel

Column drag-and-drop now supports dropping anywhere in a column (not just headers),
pressing Escape to cancel a drag, and full undo/redo integration for column reordering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): merge partial updates in updateRow to prevent column data loss

When Mothership called updateRow directly (bypassing the PATCH API route),
it passed only the changed fields — which were written as the entire row,
wiping all other columns. Move the merge logic into updateRow itself so
all callers get correct partial-update semantics, and remove the now-redundant
pre-merge from both PATCH routes.

* test(tables): add updateRow partial merge tests

Covers the bug where partial updates wiped unmentioned columns — verifies
that fields not in the update payload are preserved, nulling a field works,
full-row updates are idempotent, and missing rows throw correctly.

* feat(tables): add delete-column undo/redo, rename metadata sync, and comprehensive row ID patching

- Delete column now captures column definition, cell data, order, and width for full undo/redo
- Column rename undo/redo now properly syncs columnWidths and columnOrder metadata
- patchRedoRowId/patchUndoRowId extended to handle all action types containing row IDs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): remove source column dimming during drag reorder

Only show the insertion line at the drop position, matching Google Sheets
behavior. Remove dragSourceBounds memo and isDragging prop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): preserve selection on right-click, auto-resize on double-click, fix escape during drag

- Right-clicking within an existing selection now preserves it instead of
  resetting to a single cell, so context menu operations apply to the full range
- Double-clicking a column border auto-resizes the column to fit its content
- Escape during column drag now immediately clears refs before state update,
  preventing the dragend handler from executing the reorder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): add aria-hidden value and aria-label for column header accessibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): tighten auto-resize padding to match Google Sheets

Reduce header padding from +48px to +36px (icon + cell padding) and cell
padding from +20px to +17px (cell padding + border) for a snug fit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): clean drag ghost and clear selection on drag start

- Create a minimal custom drag image showing only the column name instead
  of the browser's default ghost that includes adjacent columns/checkboxes
- Clear any existing cell/column selection when starting a column drag to
  prevent stale highlights from persisting during reorder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(tables): add Shift+Space row selection and Ctrl+D fill down

Shift+Space now selects the entire row (all columns) instead of toggling
a checkbox, matching Google Sheets behavior. Ctrl+D copies the top cell's
value down through the selected range with full undo/redo support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): show toast on incompatible column type change

The server validates type compatibility and returns a clear error message
(e.g. "3 row(s) have incompatible values"), but the client was silently
swallowing it. Now surfaces the error via toast notification. Also moved
the undo push to onSuccess so a failed type change doesn't pollute the
undo stack.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): scroll-into-view for selection focus, Home/End origin, delete-column undo timing

- Scroll-into-view now tracks selectionFocus (not just anchor), so
  Shift+Arrow extending selection off-screen properly auto-scrolls
- Shift+Home/End now uses the current focus as origin (matching
  Shift+Arrow behavior) instead of always using anchor
- Delete column undo entry is now pushed in onSuccess, preventing
  a corrupted undo stack if the server rejects the deletion
- Dialog copy updated from "cannot be undone" to "You can undo this
  action" since undo/redo is supported

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve duplicate declarations from rebase against staging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix file upload

* fix(tables): merge column widths on delete-column undo, try/finally for auto-resize

- Delete-column undo now reads current column widths via getColumnWidths
  callback and merges the restored column's width into the full map,
  preventing other columns' widths from being wiped
- Auto-resize measurement span is now wrapped in try/finally to ensure
  DOM cleanup if an exception occurs during measurement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: revert accidental home.tsx change from rebase conflict resolution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): clear isColumnSelection on double-click and right-click, skip scroll for column select

- Clear isColumnSelection when double-clicking a cell to edit, preventing
  the column selection effect from fighting with the editing state
- Clear isColumnSelection when right-clicking outside the current
  selection, preventing stale column selection from re-expanding
- Skip scroll-into-view when isColumnSelection is true, preventing
  the viewport from jumping to the bottom row when clicking a column header

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): remove inline font override in auto-resize, guard undefined columnOrder

- Remove `font:inherit` from measurement span inline style so Tailwind
  classes (font-medium, text-small) control font properties for accurate
  column width measurement
- Only include columnOrder in metadata update when defined, preventing
  handleColumnRename from clearing a persisted column order when
  columnOrderRef is null

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): capture columnRequired in delete-column undo for full restoration

The delete-column undo action captured columnUnique but not columnRequired,
so undoing a delete on a required column would silently drop the constraint.
Now captures and restores both constraints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): restore width independently of order on delete-column undo, batch fill-down

- Column width restoration in delete-column undo no longer requires
  previousOrder to be non-null — width is restored independently
- Ctrl+D fill-down now uses batchUpdateRef (single API call) instead
  of calling mutateRef per row in a loop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): multi-column delete, select-all cell model, cut flash, chevron alignment

- Multi-select delete: detect column selection range and delete all selected
  columns sequentially with individual undo entries
- Select all (header checkbox): use cell selection model instead of checkbox
  model for consistent highlighting
- Cut flash: batch cell clears into single mutation to prevent stale data
  flashing from multiple onSettled invalidations
- Chevron alignment: adjust right padding from pr-2 to pr-2.5

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): restore column width locally on delete-column undo

Add onColumnWidthsChange callback to undo hook so restored column
widths update local component state, not just server metadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): prevent Ctrl+D bookmark dialog, batch Delete/Backspace mutations

- Move e.preventDefault() before early returns in Ctrl+D handler so
  the browser bookmark dialog is always suppressed
- Replace per-row mutateRef calls with single batchUpdateRef call in
  both Delete/Backspace handlers (checked rows and cell selection),
  consistent with cut and fill-down

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): adjust column positions for multi-column delete undo

Capture original schema positions upfront and adjust each by the
count of previously-deleted columns with lower positions, so undo
restores columns at correct server-side positions in LIFO order.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): only multi-delete when clicked column is within selection

Check that the right-clicked column is within the selected column
range before using multi-column delete. If the click is outside the
selection, delete only the clicked column.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): prevent duplicate undo entry on column drag-drop

Clear dragColumnNameRef immediately in handleColumnDragEnd so the
second invocation (from dragend after drop already fired) is a no-op.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): clean up width on delete-column redo, suppress click during drag

- Redo path for delete-column now removes the column's width from
  metadata and local state, preventing stale width entries
- Add didDragRef to ColumnHeaderMenu to suppress the click event
  that fires after a drag operation, preventing selection flash

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): remove unstable mutation object from useCallback deps

deleteTableMutation is not referentially stable — only .mutateAsync()
is. Including the mutation object causes unnecessary callback recreation
on every mutation state change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): fix auto-resize header padding, deduplicate rename metadata logic

Increase header text measurement padding from 36px to 57px to account
for the chevron dropdown button (pl-0.5 + 9px icon + pr-2.5) that
always occupies layout space. Prevents header text truncation on
auto-resize.

Deduplicate column rename metadata logic by having columnRename.onSave
call handleColumnRename instead of reimplementing the same width/order
transfer and metadata persist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): log error on cell data restoration failure during undo

Add onError handler to the batchUpdateRowsMutation inside
delete-column undo so failures are logged instead of silently
swallowed. The column schema restores first, and the cell data
restoration is a separate async call that the outer try/catch
cannot intercept.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): address audit findings across table, undo hook, and store

- Add missing bounds check in handleCopy (c >= cols.length) matching
  handleCut for defensive consistency
- Clear lastCheckboxRowRef in Ctrl+Space and Shift+Space to prevent
  stale shift-click checkbox range after keyboard selection
- Fix stale snapshot race in patchRedoRowId/patchUndoRowId by reading
  state inside the set() updater instead of via get() outside it
- Add metadata cleanup to create-column undo so column width is removed
  from both local state and server, symmetric with delete-column redo
- Remove stale width key from columnWidths on column delete instead of
  persisting orphaned entries
- Normalize undefined vs null in handleInlineSave change detection to
  prevent unnecessary mutations when oldValue is undefined
- Use ghost.parentNode?.removeChild instead of document.body.removeChild
  in drag ghost cleanup to prevent throw on component unmount

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(tables): reset didDragRef in handleDragEnd to prevent stale flag

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 01:30:32 -07:00
Vikhyath Mondreti
524f33cc9e fix(pdf): PDF previews by adding the missing preview endpoint and allowing same-origin blob URLs in iframe CSP (#4225)
* fix(pdf): PDF previews by adding the missing preview endpoint and allowing same-origin blob URLs in iframe CSP

* fixed

* add preview routes and tests

* follow nextjs route gen strat
2026-04-17 20:59:38 -07:00
Waleed
47519e34d9 fix(fireflies): support V2 webhook payload format for meetingId mapping (#4221)
* fix(fireflies): support V2 webhook payload format for meetingId mapping

Fireflies V2 webhooks use snake_case field names (meeting_id, event,
client_reference_id) instead of camelCase (meetingId, eventType,
clientReferenceId). The formatInput handler now auto-detects V1 vs V2
payloads and maps fields correctly, fixing empty meetingId on V2 webhooks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(fireflies): guard against NaN timestamp, use stricter V2 detection

Address PR review feedback:
- Use Number.isFinite guard to prevent NaN timestamp propagation
- Use AND instead of OR for V2 detection since both meeting_id and
  event are required fields in every V2 payload

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 19:43:28 -07:00
Vikhyath Mondreti
2f932054a7 fix(execution): run pptx/docx/pdf generation inside isolated-vm sandbox (#4217)
* fix(execution): run pptx/docx/pdf generation inside isolated-vm sandbox

Retires the legacy doc-worker.cjs / pptx-worker.cjs pipeline that ran user
DSL via node:vm + full require() in the same UID/PID namespace as the main
Next.js process. User code now runs inside the existing isolated-vm pool
(V8 isolate, no process / require / fs, no /proc/1/environ reachability).

Introduces a first-class SandboxTask abstraction under apps/sim/sandbox-tasks/
that mirrors apps/sim/background/ — one file per task, central typed
registry, kebab-case ids. Adding a new thing that runs in the isolate is
one file plus one registry entry.

Runtime additions in lib/execution/:
 - task-mode execution in isolated-vm-worker.cjs: load pre-built library
   bundles, run task bootstrap, run user code, run finalize, transfer
   Uint8Array result as base64 via IPC
 - named broker IPC bridge (generalizes the existing fetch bridge) with
   args size, result size, and per-execution call caps
 - cooperative AbortSignal support: cancel IPC disposes the isolate, pool
   slot is freed, pending broker-call timers are swept
 - compiled scripts + references explicitly released per execution
 - isolate.isDisposed used for cancellation detection (no error-string
   substring matching)

Library bundles (pptxgenjs, docx, pdf-lib) are built into isolate-safe
IIFE bundles by apps/sim/lib/execution/sandbox/bundles/build.ts and
committed; next.config.ts / trigger.config.ts / Dockerfile updated to
ship them instead of the deleted dist/*-worker.cjs artifacts.

Call sites migrated:
 - app/api/workspaces/[id]/pptx/preview/route.ts
 - app/api/files/serve/[...path]/route.ts (+ test mock)
 - lib/copilot/tools/server/files/{workspace-file,edit-content}.ts

All pass owner key user:<userId> for per-user pool fairness + distributed
lease accounting.

Made-with: Cursor

* improvement(sandbox): delegate timers to Node, add phase timings + saturation logs

Follow-ups on top of the isolated-vm migration (da14027b2):

Timer delegation (laverdet/isolated-vm#136 recommended pattern):
 - setTimeout / setInterval / clearTimeout / clearImmediate delegate to
   Node's real timer heap via ivm.Reference. Real delays are honored;
   clearTimeout actually cancels; ms is clamped to the script timeout
   so callbacks can't fire after the isolate is disposed.
 - Per-execution timer tracking + dispose-sweep in finally. Zero stale
   callbacks post-dispose.
 - unwrapPrimitive helper normalizes ivm.Reference-wrapped primitives
   (arguments: { reference: true } applies uniformly to all args).
 - _polyfills.ts shrinks from ~130 lines to the global->globalThis alias.
   Timers / TextEncoder / TextDecoder / console all install per-execution
   from the worker via ivm bridges.

AbortSignal race fix (pre-existing bug surfaced by the timer smoke):
 - Listener is registered after await tryAcquireDistributedLease. If the
   signal aborted during that ~200ms window (Redis down), AbortSignal
   doesn't fire listeners registered after the fact — the abort was
   silently missed. Now re-checks signal.aborted synchronously after
   addEventListener.

Observability:
 - executeTask returns IsolatedVMTaskTimings (setup, runtimeBootstrap,
   bundles, brokerInstall, taskBootstrap, harden, userCode, finalize,
   total) in every success + error path. run-task.ts logs these with
   workspaceId + queueMs so 'which tenant is slow' is queryable.
 - Pool saturation events now emit structured logger.warn with reason
   codes: queue_full_global, queue_full_owner, queue_wait_timeout,
   distributed_lease_limit. Matches the existing broker reject pattern.

Security policy:
 - New .cursor/rules/sim-sandbox.mdc codifies the hard rules for the
   worker process: no app credentials, all credentialed work goes
   through host-side brokers, every broker scopes by workspaceId.
   Pre-merge checklist for future changes to isolated-vm-worker.cjs.

Measured phase breakdown (local smoke, Redis down): pptx wall=~310ms
with bundles=~16ms, finalize=~83ms; docx ~290ms / 17ms / 70ms; pdf
~235ms / 17ms / 5ms. Bundle compilation is not the bottleneck —
library finalize is.

Made-with: Cursor

* fix(sandbox): thread AbortSignal into runSandboxTask at every call site

Three remaining callers of runSandboxTask were not threading a
cancellation signal, so a client disconnect mid-compile left the pool
slot occupied for the full 60s task timeout. Matching the pattern the
pptx-preview route already uses.

 - apps/sim/app/api/files/serve/[...path]/route.ts — GET forwards
   `request.signal` into handleLocalFile / handleCloudProxy, which
   forward into compileDocumentIfNeeded, which forwards into
   runSandboxTask.
 - apps/sim/lib/copilot/tools/server/files/workspace-file.ts — passes
   `context.abortSignal` (transport/user stop) into runSandboxTask.
 - apps/sim/lib/copilot/tools/server/files/edit-content.ts — same.

Smoke: simulated client disconnect at t=1000ms during a task that would
otherwise have waited 10s. The pool slot unwinds at t=1002ms with
AbortError; previously would have sat 60s until the task-level timeout.

Made-with: Cursor

* chore(build): raise node heap to 8GB for next build type-check

Next.js's type-check worker OOMs at the default 4GB heap on Node 23 for
this project's type graph size. Bumps the heap to 8GB only for the
`next build` invocation inside `bun run build`.

Docker builds are unaffected — `next.config.ts` sets
`typescript.ignoreBuildErrors: true` when DOCKER_BUILD=1, which skips
the type-check pass entirely. This only fixes local `bun run build`.

No functional code changes.

Made-with: Cursor

* fix lint

* refactor(copilot): dedup getDocumentFormatInfo across copilot file tools

The same extension -> { formatName, sourceMime, taskId } mapping was
duplicated in workspace-file.ts and edit-content.ts. Any future format
or task-id change had to happen in two places.

Exports getDocumentFormatInfo + DocumentFormatInfo from workspace-file.ts
(which already owned the PPTX/DOCX/PDF source MIME constants) and
imports it in edit-content.ts. Same source-of-truth pattern the file
already uses for inferContentType.

Made-with: Cursor

* fix(sandbox): propagate empty-message broker/fetch errors

Both bridges in the isolate used truthiness to detect host-side errors:

    if (response.error) throw new Error(response.error);   // broker
    if (result.error)   throw new Error(result.error);     // fetch

If a host handler ever threw `new Error('')`, err.message would be ''
(falsy), so { error: '' } was silently swallowed and the isolate saw
a successful null result. Existing call sites don't throw empty-message
errors, but the pattern was structurally unsafe.

Switch both to typeof check === 'string' and fall back to a default
message if the string is empty, so all host-reported errors propagate
into the isolate regardless of message content.

Made-with: Cursor
2026-04-17 19:07:46 -07:00
Vikhyath Mondreti
319e0db732 improvement(mothership): agent model dropdown validations, markers for recommended models (#4213)
* improvement(mothership): agent model dropdown validations, recommendation system

* mark a few more models:

* remove regex based checks'

* remove dead code

* remove inherited reseller flags

* fix note

* address bugbot comments

* code cleanup
2026-04-17 18:58:02 -07:00
Waleed
003e931546 improvement(terminal): resize output panel on any layout change via ResizeObserver (#4220)
Replaces MutationObserver on document.documentElement (watching CSS variable
changes) + window resize listener with a ResizeObserver on the terminal element
itself. The terminal now measures its own rendered width directly, so it responds
correctly to all layout changes — sidebar, workflow panel, and mothership resize —
without indirect CSS variable plumbing or cross-component coupling.
2026-04-17 18:23:51 -07:00
Waleed
948cdbcc3f fix(chat): prevent @-mention menu focus loss and stabilize render identity (#4218)
* fix(docs): preserve gif playback position in lightbox and clean up ui components

- Capture currentTime on click and seek lightbox video to match using useLayoutEffect
- Convert lightboxStartTime from useState to useRef (no independent render needed)
- Apply same fix to ActionVideo in action-media.tsx
- Remove dead AnimatedBlocks component (zero imports)
- Fix language-dropdown to derive currentLang during render instead of mirroring into state via effect
- Replace template literals with cn() in faq.tsx and video.tsx

* fix(chat): prevent @-mention menu focus loss and stabilize render identity

Radix DropdownMenu's FocusScope was restoring focus from the search input
to the content root whenever registered menu items mounted or unmounted
inside the content, interrupting typing after a keystroke or two.

- Keep the default tree always mounted under `hidden` instead of swapping
  subtrees when the filter activates.
- Render filtered results as plain <button role="menuitem"> so they do not
  participate in Radix's menu Collection.
- Add activeIndex state with ArrowUp/Down/Enter keyboard nav, mouse-hover
  sync, and scrollIntoView so the highlighted row stays visible and users
  can see what Enter will select.

While tracing the cascade that compounded the bug:

- Hoist `select` in useWorkflowMap / useWorkspacesQuery / useFolderMap to
  module scope so TanStack Query caches the select result across renders.
- Guard setSelectedContexts([]) with a functional updater that bails out
  when already empty, preventing a fresh [] literal from invalidating
  consumers that key on reference identity.
- Wrap WorkspaceHeader in React.memo so it bails out on parent renders
  once its (now-stable) props are unchanged.

Made-with: Cursor

* remove extraneous comments

* cleanup

* fix(chat): apply same setState bail-out to clearContexts for consistency

Matches the invariant we already established for the message effect:
calling setSelectedContexts([]) against an already-empty array emits a
fresh [] reference (Object.is bails out are not reference-level), which
cascades through consumers that key on selectedContexts identity.
clearContexts is part of the hook's public API so callers can't know
whether the list is empty — make it safe for them.

Made-with: Cursor
2026-04-17 17:38:37 -07:00
Theodore Li
5e716d74bc docs(assets): Add pics and videos for mothership (#4216)
* Add pics and videos for mothership

* Minimal edit
2026-04-17 16:31:34 -04:00
Waleed
e1018f1c72 improvement(utils): add shared utility functions and replace inline patterns (#4214)
* improvement(utils): add shared utility functions and replace inline patterns

Add sleep, toError, safeJsonParse, isNonNull helpers and invariant/assertNever
assertions. Replace all inline implementations across the codebase with these
shared utilities for consistency. Zero behavioral changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(agiloft): remove import type from .server module to fix client bundle build

Turbopack resolves .server.ts modules even for type-only imports,
pulling dns/promises into client bundles. Define SecureFetchResponse
locally instead.

* fix(agiloft): revert to client-safe imports to fix build

The SSRF upgrade to input-validation.server introduced dns/promises
into client bundles via tools/registry.ts. Revert to the original
client-safe validateExternalUrl + fetch. The SSRF DNS-pinning upgrade
for agiloft directExecution should be done via API routes in a
separate PR.

* feat(agiloft): add API route for retrieve_attachment, matching established file patterns

Convert retrieve_attachment from directExecution to standard API route
pattern, consistent with Slack download and Google Drive download tools.

- Create /api/tools/agiloft/retrieve with DNS validation, auth lifecycle,
  and base64 file response matching the { file: { name, mimeType, data,
  size } } convention
- Update retrieve_attachment tool to use request/transformResponse
  instead of directExecution, removing the dependency on
  executeAgiloftRequest from the tool definition
- File output type: 'file' enables FileToolProcessor to store downloaded
  files in execution filesystem automatically

* shopify

* fix(agiloft): add optional flag to nullable lock record block outputs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(agiloft): revert optional flag on block outputs — property only exists on tool outputs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore(utils): remove unused utilities (asserts, safeJsonParse, isNonNull)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 13:29:42 -07:00
Waleed
351873ac04 improvement(sidebar): interleave folders and workflows by sort order in all resource pickers (#4215)
* improvement(sidebar): interleave folders and workflows by sort order in all resource pickers

- Merge folder/workflow submenus into a single Workflows tree sorted by sortOrder in both the @ plus-menu and add-resource dropdowns
- Widen both dropdowns from 240px to 320px and remove type labels from search results
- Fix isOpen/onSwitch regression: WorkflowFolderTreeItems now forwards node.isOpen so already-open tabs are switched to rather than duplicated
- Apply same interleaved sortOrder ordering to the collapsed sidebar's root-level folder+workflow list

* fix(add-resource-dropdown): align sort tiebreaker with compareByOrder, document empty-folder omission

Use id.localeCompare as the sort tiebreaker in buildWorkflowFolderTree to match the sidebar's
compareByOrder fallback (sortOrder → id) instead of name. Add a comment clarifying that empty
folders are intentionally omitted from the tree view.

* chore: remove extraneous inline comment
2026-04-17 13:01:44 -07:00
Waleed
38864fac34 feat(monday): add full Monday.com integration (#4210)
* feat(monday): add full Monday.com integration with tools, block, triggers, and OAuth

Adds a comprehensive Monday.com integration:
- 13 tools: list/get boards, CRUD items, search, subitems, updates, groups, move, archive
- Block with operation dropdown, board/group selectors, OAuth credential, advanced mode
- 9 webhook triggers with auto-subscription lifecycle (create/delete via GraphQL API)
- OAuth config with 7 scopes (boards, updates, webhooks, me:read)
- Provider handler with challenge verification, formatInput, idempotency
- Docs, icon, selectors, and all registry wiring

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(monday): cast userId to string in deleteSubscription fallback

The DeleteSubscriptionContext type has userId as unknown, causing a
TypeScript error when passing it to getOAuthToken which expects string.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(monday): escape string params in GraphQL, align deleteSubscription with established patterns

- Use JSON.stringify() for groupId in get_items.ts (matches create_item.ts
  and move_item_to_group.ts)
- Use JSON.stringify() for notificationUrl in webhook provider
- Remove non-standard getOAuthToken fallback in deleteSubscription to match
  Airtable/Webflow pattern (credential resolution only, warn and return on failure)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(monday): sanitize columns JSON in search_items GraphQL query

Parse and re-stringify the columns param to ensure well-formed JSON
before interpolating into the GraphQL query, preventing injection
via malformed input.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(monday): validate all numeric IDs and sanitize columns in GraphQL queries

- Add sanitizeNumericId() helper to tools/monday/utils.ts for consistent
  validation across all tool body builders
- Apply to all 13 instances of boardId, itemId, parentItemId interpolation
  across 11 tool files, preventing GraphQL injection via crafted IDs
- Wrap JSON.parse in search_items.ts with try-catch for user-friendly
  error on malformed column filter JSON

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(monday): deduplicate numeric ID validation, sanitize limit/page params

- Refactor sanitizeNumericId to delegate to validateMondayNumericId
  from input-validation.ts, eliminating duplicated regex logic
- Add sanitizeLimit helper for safe integer coercion with bounds
- Apply sanitizeLimit to limit/page params in list_boards, get_items,
  and search_items for consistent validation across all GraphQL params

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(monday): align list_boards limit description with code (max 500)

The param description said "max 100" but sanitizeLimit caps at 500,
which is what Monday.com's API supports for boards. Updated both the
tool description and docs to say "max 500".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 20:27:44 -07:00
Waleed
2266bb384b feat(triggers): add Atlassian triggers for Jira, JSM, and Confluence (#4211)
* feat(triggers): add Atlassian triggers for Jira, JSM, and Confluence

- Jira: add 9 new triggers (sprint created/started/closed, project created, version released, comment updated/deleted, worklog updated/deleted)
- JSM: add 5 triggers from scratch (request created/updated/commented/resolved, generic webhook)
- Confluence: add 7 new triggers (comment updated, attachment updated, page/blog restored, space removed, page permissions updated, user created)
- Add JSM webhook provider handler with HMAC validation and changelog-based event matching
- Add Atlassian webhook identifier to idempotency service for native dedup
- Add extractIdempotencyId to Confluence handler
- Fix Jira generic webhook to pass through full payload for non-issue events
- Fix output schemas: add description (ADF), updateAuthor, resolution, components, fixVersions, worklog timestamps, note emailAddress as Jira Server only

* fix(triggers): replace any with Record<string, unknown> in confluence extract functions

* lint

* fix(triggers): use comment.id in JSM idempotency, fix confluence type cast

JSM extractIdempotencyId now prioritizes comment.id over issue.id for
comment_created events, matching Jira's documented webhook payload
structure. Also fixes type cast for confluence extract function calls.

* fix(triggers): correct comment.body type to json, fix TriggerOutput description type

- JSM webhook comment.body changed from string to json (ADF format)
- Widened TriggerOutput.description to accept TriggerOutput objects,
  removing unsafe `as unknown as string` casts for Jira description fields
2026-04-16 19:59:12 -07:00
Vikhyath Mondreti
a589c8e318 improvement(mothership): whitespace only deltas need to be preserved, update docs for theshold billing (#4212)
* fix(mothership): content block spaces trimmed

* update overage threshold docs
2026-04-16 19:22:01 -07:00
Vikhyath Mondreti
3d909d5416 fix(resolver): turn off resolver for opaque schema nodes, unrun paths (#4208)
* fix(resolver): turn off resolver for opaque schema nodes, unrun paths

* fix subflows to make them consistent

* fix tests
2026-04-16 18:33:28 -07:00
JaeHyung Jang
3e2a7a2eb1 fix(export): preserve unicode characters in workflow filenames (#4120)
Previously, Non-ASCII characters (like Korean) in workflow names were
replaced by dashes during export because of a restrictive regex.
This update uses a Unicode-aware regex to allow letters and numbers
from any language while still sanitizing unsafe filesystem characters.

fixes #4119

Signed-off-by: JaeHyung Jang <jaehyung.jang@navercorp.com>
2026-04-16 18:18:56 -07:00
Waleed
49a1495e15 improvement(logs): fix trigger badge wrapping, time range picker, status filters, and React anti-patterns (#4207)
* improvement(logs): fix trigger badge wrapping, time range picker, status filters, and React anti-patterns

* chore(logs): remove dev mock logs

* fix(logs): prevent DatePicker onOpenChange from reverting time range after Apply
2026-04-16 18:00:57 -07:00
Waleed
1d0e118eef fix(socket): sync deploy button state across collaborators (#4206)
* fix(socket): sync deploy button state across collaborators

Broadcast workflow-deployed events via socket so all connected users
invalidate their deployment query cache when any user deploys, undeploys,
activates a version, or triggers a deploy through chat/form endpoints.

* fix(socket): check response status on deployment notification

Log a warning when the socket server returns a non-2xx status for
deployment notifications, matching the pattern in lifecycle.ts.

* improvement(config): consolidate socket server URL into getSocketServerUrl/getSocketUrl

Replace all inline `env.SOCKET_SERVER_URL || 'http://localhost:3002'` and
`getEnv('NEXT_PUBLIC_SOCKET_URL') || 'http://localhost:3002'` with centralized
utility functions in urls.ts, matching the getBaseUrl() pattern.

* improvement(config): consolidate Ollama URL and CSP socket/Ollama hardcodes

Add getOllamaUrl() to urls.ts and replace inline env.OLLAMA_URL fallbacks
in the provider and API route. Update CSP to use getSocketUrl(),
getOllamaUrl(), and a local toWebSocketUrl() helper instead of hardcoded
localhost strings.

* lint

* fix(tests): add missing mocks for new URL utility exports

Update lifecycle, async execute, and chat manage test mocks to include
getSocketServerUrl, getOllamaUrl, and notifySocketDeploymentChanged.

* fix(csp): remove urls.ts import to fix next.config.ts build

CSP is loaded by next.config.ts which transpiles outside the @/ alias
context. Use local constants instead of importing from urls.ts.

* fix(queries): invalidate chat and form status on deployment change

Add chatStatus and formStatus to invalidateDeploymentQueries so all
deployment-related queries refresh when any user deploys or undeploys.
2026-04-16 17:46:53 -07:00
Waleed
c06361b142 improvement(tables): clean up duplicate types, unnecessary memos, and barrel imports (#4205)
* improvement(tables): clean up duplicate types, unnecessary memos, and barrel imports

* fix(tables): revert barrel import in client component to avoid bundling server-only deps
2026-04-16 16:47:51 -07:00
Waleed
6fd1767c7e improvement(ui): remove React anti-patterns, fix CSP violations (#4203)
* improvement(ui): remove React anti-patterns, fix CSP violations

* fix(ui): restore useMemo on existingKeys — it is observed by useAvailableResources

* improvement(ui): add RefreshCw icon, update Bell SVG, active state styling for header actions

* minor UI improvements
2026-04-16 13:58:15 -07:00
Vikhyath Mondreti
6aa6346330 fix(executor): subflow edge keys mismatch (#4202)
* fix(executor): subflow edge keys mismatch'

* improve style
2026-04-16 13:41:11 -07:00
Vikhyath Mondreti
1708bbee35 feat(tables): import csv into existing tables (#4199)
* feat(tables): import csv into existing tables

* update types

* address comments

* address comment
2026-04-16 13:37:54 -07:00
Waleed
e16c8e6f70 fix(ui): stop terminal auto-select from stealing copilot input focus (#4201) 2026-04-16 12:44:26 -07:00
Waleed
9f41736d50 fix(misc): remove duplicate docs page, update clopus 4.7 (#4200)
* fix(misc): remove duplicate docs page, update clopus 4.7

* fix(docs): consolidate duplicate docs and fix SDK API signatures

- Remove duplicate custom-tools page (custom-tools/index.mdx → tools/custom-tools.mdx is canonical)
- Remove comparison table from custom-tools per product preference
- Fix permissions inconsistency: delete now requires Admin across all docs
- Consolidate sdks/ into api-reference/ (sdks/ directory deleted)
- Fix Python SDK docs: correct param is `input`, not `input_data`
- Fix TypeScript SDK docs: correct signature is executeWorkflow(id, input, options) not options-object form
- Add FAQ sections to both SDK reference pages

* fix(docs): update SDKs card links from /sdks to /api-reference

* fix(docs): update /sdks references to /api-reference in llms.txt files
2026-04-16 12:33:25 -07:00
Waleed
147ac89672 feat(docs): fill documentation gaps across platform features (#4110)
* feat(docs): fill documentation gaps across platform features

* fix(docs): address PR review comments on chat OTP cookies and MCP env var placeholders

* fix(docs): replace smart quotes with straight quotes in JSX attributes

* update(docs): update mcp, custom tools, and variables docs

* Fix grammar

* mothership docs, tags, connectors, api, chat deploy, etc

* more info

* more

* feat(docs): auto-generate per-provider trigger documentation

Extends scripts/generate-docs.ts to produce one MDX page per trigger
provider (39 pages) in apps/docs/content/docs/en/triggers/. The 5
hand-written pages (index, start, schedule, webhook, rss) are never
touched.

Key additions to the generation script:
- resolveConstVariable() resolves module-level const spreads so
  providers like Vercel that build outputs from const variables (not
  just functions) are fully documented
- resolveTriggerBuilderFunction() extended to expand variable spreads
  (...varName) in addition to function-call spreads (...fn())
- groupTriggersByProvider() deduplicates v1/v2 trigger variants by
  name, keeping the highest-versioned one per provider
- writeIconMapping() adds bare-name aliases for versioned block types
  (github_v2 → github, fireflies_v2 → fireflies, etc.) so
  BlockInfoCard resolves icons for all 39 trigger providers
- extractTriggerConfigFields() filters readOnly display blocks (webhook
  URL displays, sample payloads, curl examples) from config tables

Each generated page includes: BlockInfoCard with correct icon/color,
trigger count, polling note where applicable, Configuration table, and
Output table for every trigger. No "Type:" lines.

* refactor(docs): align trigger docs structure with tools docs

- Use ### `trigger_id` headings (matching ### `tool_id` in tools docs)
- Wrap all trigger sections under a ## Triggers header
- Rename Configuration/Output to #### level (matching #### Input/Output)
- Use Parameter column header to match tools docs table style
- Map UI widget types to semantic types: short-input/long-input/dropdown
  → string, switch → boolean, slider → number, oauth-input → string

* refactor(docs): use human-readable names for trigger section headings

Trigger IDs are internal identifiers; users scan by name. Switch from
### `trigger_id` to ### Trigger Name for cleaner sidebar navigation
and better readability.

* fix(docs): resolve subBlock builder functions for all trigger Config sections

Extends generate-docs.ts to parse subBlock builder functions so all 15
providers previously missing Configuration sections now generate them.

Handles three patterns:
- `buildTriggerSubBlocks({extraFields: buildX(...)})` — extracts extra
  fields from the call site and resolves them from the provider's utils.ts
- `return [...]` — direct array return (Attio, Confluence, etc.)
- `blocks.push(...)` — imperative push pattern (Linear, Ashby)

Also resolves const-reference field IDs (SCREAMING_CASE) by searching
the webhook provider constants cache, fixing Gong's `gongJwtPublicKeyPem`
field which was previously unresolvable. Adds title-as-description fallback
for OAuth credential fields that have no explicit description.

* fix(docs): correctly destructure nested implicit-object trigger outputs

Fixes a parser bug where output fields with no top-level `type` key but
child fields each having their own `type`/`description` were incorrectly
parsed. The `type:` and `description:` regex matches were not
depth-aware, so values from nested children bled into the parent field.

Changes:
- Add `isAtDepthZero()` helper for brace-depth-aware regex matching
- Fix `parseFieldContent` to only match `type:` at brace depth 0
- Fix `extractDescription` to only match `description:` at brace depth 0
- Add implicit-object fallback: when no top-level `type` exists but child
  fields have their own types, treat as `object` with `properties`
- Regenerate all affected trigger docs (Cal.com payload, Linear data,
  Jira issue.fields, Ashby application, Greenhouse candidate, etc.)

* chore(docs): update static trigger and start page images

* feat(providers): add claude-opus-4-7 model with adaptive thinking support

* Add workflow version screenshots

* Add function block screenshots

---------

Co-authored-by: Theodore Li <theo@sim.ai>
2026-04-16 11:51:49 -07:00
Theodore Li
4cdc941490 fix(ui): fix focusing bugs while editing files (#4197) 2026-04-16 14:21:10 -04:00
Waleed
0464a57601 fix(ui): posthog guard, dynamic import loading, compact variant, rebase cleanup (#4196)
* v0.6.29: login improvements, posthog telemetry (#4026)

* feat(posthog): Add tracking on mothership abort (#4023)

Co-authored-by: Theodore Li <theo@sim.ai>

* fix(login): fix captcha headers for manual login  (#4025)

* fix(signup): fix turnstile key loading

* fix(login): fix captcha header passing

* Catch user already exists, remove login form captcha

* fix(ui): posthog guard, dynamic import loading, compact variant, rebase cleanup

---------

Co-authored-by: Theodore Li <theodoreqili@gmail.com>
2026-04-15 23:52:57 -07:00
Emir Karabeg
23ccd4a50c improvement(landing): optimize core web vitals and accessibility (#4193)
* improvement(landing): optimize core web vitals and accessibility

Code-split AuthModal and DemoRequestModal via next/dynamic across 7 landing
components to move auth-client bundle (~150-250KB) out of the initial JS payload.
Replace useSession import in navbar with direct SessionContext read to avoid
pulling the entire better-auth client into the landing page bundle. Add immutable
cache header for content-hashed _next/static assets. Defer PostHog session
recording until user identification to avoid loading the recorder (~80KB) on
anonymous visits. Fix accessibility issues flagged by Lighthouse: add missing
aria-label on preview submit button, add inert to aria-hidden ReactFlow wrapper,
set decorative alt on logos inside labeled links, disambiguate duplicate footer
API links.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(posthog): guard startSessionRecording against repeated calls on refetch

The effect fires on every session reload (e.g., subscription upgrade).
Calling startSessionRecording() while already recording fragments the
session in the analytics dashboard. Add sessionRecordingStarted() guard
so recording only starts once per page lifecycle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(config): remove redundant _next/static cache header

Next.js already sets Cache-Control: public, max-age=31536000, immutable
on _next/static assets natively and this cannot be overridden. The custom
rule was redundant on Vercel and conflicted with the extension-based rule
on self-hosted deployments due to last-match-wins ordering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:56:16 -07:00
Theodore Li
ba6bc91681 fix(ui): fix attachment logic on queued mothership messages (#4191)
* fix(ui): fix attachment logic on queued mothership messages

* Add focus after hitting pencil button for queued message

* fix copilot layout
2026-04-15 21:42:48 -04:00
Vikhyath Mondreti
377712c9f3 fix(mothership): chat stream structuring + logs resource post fix (#4189)
* fix(mothership): chat streaming structure

* fix logs resource thinking bug"

* address comments

* address comments
2026-04-15 16:43:22 -07:00
Waleed
6dddc3f796 fix(brightdata): fix async Discover API, echo-back fields, and registry ordering (#4188)
* fix(brightdata): use params for echo-back fields in transformResponse

transformResponse receives params as its second argument. Use it to
return the original url, query, snapshotId, and searchEngine values
instead of hardcoding null or extracting from response data that may
not contain them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(brightdata): handle async Discover API with polling

The Bright Data Discover API is asynchronous — POST /discover returns
a task_id, and results must be polled via GET /discover?task_id=...
The previous implementation incorrectly treated it as synchronous,
always returning empty results.

Uses postProcess (matching Firecrawl crawl pattern) to poll every 3s
with a 120s timeout until status is "done".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(brightdata): alphabetize block registry entry

Move box before brandfetch/brightdata to maintain alphabetical ordering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* lint

* fix(brightdata): return error objects instead of throwing in postProcess

The executor wraps postProcess in try-catch and falls back to the
intermediate transformResponse result on error, which has success: true
with empty results. Throwing errors would silently return empty results.

Match Firecrawl's pattern: return { ...result, success: false, error }
instead of throwing. Also add taskId to BrightDataDiscoverResponse type
to eliminate unsafe casts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(brightdata): use platform execution timeout for Discover polling

Replace hardcoded 120s timeout with DEFAULT_EXECUTION_TIMEOUT_MS to
match Firecrawl and other async polling tools. Respects platform-
configured limits (300s free, 3000s paid).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 16:20:39 -07:00
Waleed
cd8c5bd0b8 fix(logs): close sidebar when selected log disappears from filtered list + cleanup (#4186)
Derive sidebar open state from selection validity instead of using a
separate useEffect. Also removes unnecessary useMemo/useCallback in
non-memo'd components, replaces useEffect with render-time reset in
dashboard, fixes CSS tokens, and adds hierarchical query key factory.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 12:58:22 -07:00
Siddharth Ganesan
f0285adc38 fix(mothership): fix superagent credentials (#4185)
* Fix

* Fix ajv csp issue

* Lint
2026-04-15 12:52:02 -07:00
Waleed
a39dc158cf feat(brightdata): add Bright Data integration with 8 tools (#4183)
* feat(brightdata): add Bright Data integration with 8 tools

Add complete Bright Data integration supporting Web Unlocker, SERP API,
Discover API, and Web Scraper dataset operations. Includes scrape URL,
SERP search, discover, sync scrape, scrape dataset, snapshot status,
download snapshot, and cancel snapshot tools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(brightdata): address PR review feedback

- Fix truncated "Download Snapshot" description in integrations.json and docs
- Map engine-specific query params (num/count/numdoc, hl/setLang/lang/kl,
  gl/cc/lr) per search engine instead of using Google-specific params for all
- Attempt to parse snapshot_id from cancel/download response bodies instead
  of hardcoding null

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* lint

* fix(agiloft): change bgColor to white; fix docs truncation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(brightdata): avoid inner quotes in description to fix docs generation

The docs generator regex truncates at inner quotes. Reword the
download_snapshot description to avoid embedded double quotes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(brightdata): disable incompatible DuckDuckGo and Yandex URL params

DuckDuckGo kl expects region-language format (us-en) and Yandex lr
expects numeric region IDs (213), not plain two-letter codes. Disable
these URL-level params since Bright Data normalizes localization through
the body-level country param.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 12:47:02 -07:00
Waleed
05c1c5b1f6 fix(gemini): support structured output with tools on Gemini 3 models (#4184)
* v0.6.29: login improvements, posthog telemetry (#4026)

* feat(posthog): Add tracking on mothership abort (#4023)

Co-authored-by: Theodore Li <theo@sim.ai>

* fix(login): fix captcha headers for manual login  (#4025)

* fix(signup): fix turnstile key loading

* fix(login): fix captcha header passing

* Catch user already exists, remove login form captcha

* fix(gemini): support structured output with tools on Gemini 3 models

* fix(home): remove duplicate handleStopGeneration declaration

* refactor(gemini): use prefix-based Gemini 3 model detection

---------

Co-authored-by: Theodore Li <theodoreqili@gmail.com>
2026-04-15 12:21:39 -07:00
Emir Karabeg
5274efd8f9 improvement(seo): optimize sitemaps, robots.txt, and core web vitals across sim and docs (#4170)
* improvement(seo): optimize sitemaps and robots.txt across sim and docs

- Add missing pages to sim sitemap: blog author pages, academy catalog and course pages
- Fix 6x duplicate URL bug in docs sitemap by deduplicating with source.getLanguages()
- Convert docs sitemap from route handler to Next.js metadata convention with native hreflang
- Add x-default hreflang alternate for docs multi-language pages
- Remove changeFrequency and priority fields (Google ignores both)
- Fix inaccurate lastModified timestamps — derive from real content dates, omit when unknown
- Consolidate 20+ redundant per-bot robots rules into single wildcard entry
- Add /form/ and /credential-account/ to sim robots disallow list
- Reference image sitemap in sim robots.txt
- Remove deprecated host directive from sim robots
- Move disallow rules before allow in docs robots for crawler compatibility
- Extract hardcoded docs baseUrl to env variable with production fallback

* fix(seo): remove homepage new Date(), guard latestModelDate empty array

* improvement(seo): consolidate DOCS_BASE_URL, optimize core web vitals

Extract hardcoded https://docs.sim.ai into shared DOCS_BASE_URL constant
in lib/urls.ts and replace all 20+ instances across layouts, metadata,
structured data, LLM manifest, sitemap, and robots files. Remove
OneDollarStats analytics script and tighten CSP for improved core web vitals.

* fix: removed onedollarstats from bun lock

* fix(seo): guard per-provider Math.max, consolidate docs robots to single wildcard
2026-04-15 12:13:30 -07:00
Waleed
0b36c8bcb6 fix(landing): return 404 for invalid dynamic route slugs (#4182)
* v0.6.29: login improvements, posthog telemetry (#4026)

* feat(posthog): Add tracking on mothership abort (#4023)

Co-authored-by: Theodore Li <theo@sim.ai>

* fix(login): fix captcha headers for manual login  (#4025)

* fix(signup): fix turnstile key loading

* fix(login): fix captcha header passing

* Catch user already exists, remove login form captcha

* fix(landing): return 404 for invalid dynamic route slugs

Add `dynamicParams = false` to all landing page dynamic routes so
Next.js returns a proper 404 instead of a client-side exception for
slugs not in generateStaticParams.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(home): remove duplicate handleStopGeneration declaration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Theodore Li <theodoreqili@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 11:48:39 -07:00
Waleed
842aa2c254 fix(csp): add missing analytics domains, remove unsafe-eval, fix workspace CSP gap (#4179) 2026-04-15 10:04:53 -07:00
Waleed
ff71a07e8f improvement(ui): rename user-facing "execution" to "run" (#4176)
* v0.6.29: login improvements, posthog telemetry (#4026)

* feat(posthog): Add tracking on mothership abort (#4023)

Co-authored-by: Theodore Li <theo@sim.ai>

* fix(login): fix captcha headers for manual login  (#4025)

* fix(signup): fix turnstile key loading

* fix(login): fix captcha header passing

* Catch user already exists, remove login form captcha

* improvement(ui): rename user-facing "execution" to "run"

* fix(mothership): remove duplicate handleStopGeneration declaration

* chore: remove verbose comment in cancel route

* fix(ui): missed execution → run renames in search suggestions and error fallback

---------

Co-authored-by: Theodore Li <theodoreqili@gmail.com>
2026-04-14 21:49:20 -07:00
Waleed
22d4639f13 refactor(microsoft-excel): export GRAPH_ID_PATTERN and deduplicate validation (#4174)
* refactor(microsoft-excel): export GRAPH_ID_PATTERN and reuse across routes

Export the shared regex pattern from utils.ts and import it in files/route.ts
and drives/route.ts instead of duplicating the inline pattern. Also reorders
the TSDoc comment to sit above getItemBasePath where it belongs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* lint

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 21:34:54 -07:00
Waleed
80095788fc feat(microsoft-excel): add SharePoint drive support for Excel integration (#4162)
* feat(microsoft-excel): add SharePoint drive support for Excel integration

* fix(microsoft-excel): address PR review comments

- Validate siteId/driveId format in drives route to prevent path traversal
- Use direct single-drive endpoint for fetchById instead of filtering full list
- Fix dependsOn on sheet/spreadsheet selectors so driveId flows into context
- Fix NextRequest type in drives route for build compatibility

* fix(microsoft-excel): validate driveId in files route

Add regex validation for driveId query param in the Microsoft OAuth
files route to prevent path traversal, matching the drives route.

* fix(microsoft-excel): unblock OneDrive users and validate driveId in sheets route

- Add credential to any[] arrays so OneDrive users (no drive selected)
  still pass the dependsOn gate while driveSelector remains in the
  dependency list for context flow to SharePoint users
- Add /^[\w-]+$/ validation for driveId in sheets API route

* fix(microsoft-excel): validate driveId in getItemBasePath utility

Add regex validation for driveId at the shared utility level to prevent
path traversal through the tool execution path, which bypasses the
API route validators.

* fix(microsoft-excel): use centralized input validation

Replace inline regex validation with platform validators from
@/lib/core/security/input-validation:
- validateSharePointSiteId for siteId in drives route
- validateAlphanumericId for driveId in drives, sheets, files routes
  and getItemBasePath utility

* lint

* improvement(microsoft-excel): add File Source dropdown to control SharePoint visibility

Replace always-visible optional SharePoint fields with a File Source
dropdown (OneDrive/SharePoint) that conditionally shows site and drive
selectors. OneDrive users see zero extra fields (default). SharePoint
users switch the dropdown and get the full cascade.

* fix(microsoft-excel): fix canonical param test failures

Make fileSource dropdown mode:'both' so it appears in basic and advanced
modes. Add condition to manualDriveId to match driveSelector's condition,
satisfying the canonical pair consistency test.

* fix(microsoft-excel): address PR review feedback for SharePoint drive support

- Clear stale driveId/siteId/spreadsheetId when fileSource changes by adding
  fileSource to dependsOn arrays for siteSelector, driveSelector, and
  spreadsheetId selectors
- Reorder manualDriveId before manualSpreadsheetId in advanced mode for
  logical top-down flow
- Validate spreadsheetId with validateMicrosoftGraphId in getItemBasePath()
  and sheets route to close injection vector (uses permissive validator that
  accepts ! chars in OneDrive item IDs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(microsoft-excel): use validateMicrosoftGraphId for driveId validation

SharePoint drive IDs use the format b!<base64-string> which contains !
characters rejected by validateAlphanumericId. Switch all driveId
validation to validateMicrosoftGraphId which blocks path traversal and
control characters while accepting valid Microsoft Graph identifiers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(microsoft-excel): use validatePathSegment with strict pattern for driveId/spreadsheetId

Replace validateMicrosoftGraphId with validatePathSegment using a custom
pattern ^[a-zA-Z0-9!_-]+$ for all URL-interpolated IDs. validatePathSegment
blocks /, \, path traversal, and null bytes before checking the pattern,
preventing URL-modifying characters like ?, #, & from altering the Graph
API endpoint. The pattern allows ! for SharePoint b!<base64> drive IDs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* lint

* fix(microsoft-excel): reorder driveId before spreadsheetId in v1 block

Move driveId subBlock before manualSpreadsheetId in the legacy v1 block
to match the logical top-down flow (Drive ID → Spreadsheet ID), consistent
with the v2 block ordering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(microsoft-excel): clear manualDriveId when fileSource changes

Add dependsOn: ['fileSource'] to manualDriveId so its value is cleared
when switching from SharePoint back to OneDrive. Without this, the stale
driveId would still be serialized and forwarded to getItemBasePath,
routing through the SharePoint drive path instead of me/drive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(microsoft-excel): use getItemBasePath in sheets route to remove duplication

Replace inline URL construction and validation logic with the shared
getItemBasePath utility, eliminating duplicated GRAPH_ID_PATTERN regex
and conditional URL building.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* lint

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 21:10:55 -07:00
Waleed
61b33e5978 fix(blocks): correct required field validation for Jira and Confluence blocks (#4172)
* fix(blocks): correct required field validation for Jira and Confluence blocks

Jira: summary is only required for create (not update), projectId is not required for update (API uses issueKey). Confluence: title and content are required for page creation, title is required for blog post creation — all enforced by backend validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(blocks): remove projectId dependsOn gate for update fields, require content for blog post creation

Jira: Remove dependsOn projectId from shared write/update fields — projectId is not required for update so the gate would disable all update fields when no project is selected. Write-only fields (issueType, parentIssue, reporter) retain the gate since projectId is required for create.

Confluence V2: Add create_blogpost to content required condition — backend Zod schema enforces content for blog post creation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* lint

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 20:44:47 -07:00
Siddharth Ganesan
29fbad2874 fix(mothership): fix intelligence regression (#4171) 2026-04-14 20:01:44 -07:00