mirror of
https://github.com/simstudioai/sim.git
synced 2026-10-24 11:36:37 +08:00
d1eb79ecd35efbe917869209de68ae3536145da2
4560
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f708462213 |
fix(files): skip zip and return plain .md when no embedded images (#4498)
* fix(files): skip zip and return plain .md when no embedded images * fix(files): use imageIds.length guard instead of assetMap.size * fix(files): move imageIds.length guard before async fetch to avoid unnecessary work |
||
|
|
38cbefdc3b |
fix(revenuecat): align tools and block with REST v1 API spec (#4488)
* fix(revenuecat): align tools and block with REST v1 API spec
- Validated all 10 tools and the block against context7 REST v1 docs
- Unwrap {value:{subscriber}} envelope across post-receipts, attributes,
entitlements, and Google subscription endpoints
- Trim entitlement output to documented fields (expires_date,
grace_period_expires_date, product_identifier, purchase_date)
- Add subscriber output fields: last_seen, original_application_version,
other_purchases, subscriber_attributes
- create_purchase: productId optional (Google-only required); add
introductoryPrice, attributes, updated_at_ms; surface customer + subscriber;
X-Platform required; presentedOfferingIdentifier and paymentMode
- update_subscriber_attributes: read response and surface subscriber;
note required updated_at_ms
- defer_google_subscription: enforce XOR(extendByDays, expiryTimeMs) and
1-365 range; expiryTimeMs as one-of alternative
- grant_entitlement: duration optional, added endTimeMs (one-of)
- refund_google_subscription: corrected endpoint to
/transactions/{storeTransactionId}/refund
- delete_customer: read 'deleted' field (was 'was_deleted')
- list_offerings: corrected X-Platform values
- get_customer: count active subscriptions by expiry/refund
- Added shared throwIfRevenueCatError helper for {code, message} envelope
- Moved type coercions from tools.config.tool to tools.config.params to
preserve dynamic refs
* docs
* fix(revenuecat): address PR review feedback
- create_purchase: wrap JSON.parse(attributes) with try/catch and clear error
- update_subscriber_attributes: drop subscriber output (endpoint returns
empty body) and guard JSON.parse on attributes
- grant_entitlement: throw when both duration and endTimeMs are provided,
matching defer_google_subscription behavior
* fix(revenuecat): tighten docs after sub-segment validation
- delete_customer: drop dead was_deleted fallback (docs specify 'deleted')
- grant_entitlement: mark duration + startTimeMs as deprecated, clarify
startTimeMs only affects expiration calc (not grant time)
- list_offerings: replace vague platform description with documented
X-Platform enum (ios, android, amazon, stripe, roku, paddle)
* docs
* fix(revenuecat): clear duration default when endTimeMs is provided
The duration dropdown defaults to 'monthly' so any user filling in the
advanced endTimeMs field would otherwise hit the XOR guard. Clear
duration in the params mapper so endTimeMs takes precedence.
* fix(revenuecat): clear extendByDays default when expiryTimeMs is provided
Mirror the duration/endTimeMs fix from
|
||
|
|
d081ab283e |
fix(logs): relax fileSchema so execution logs with files render again (#4495)
* fix(logs): relax fileSchema so execution logs with files render again * improvement(logs): align fileSchema with shared UserFile type - contracts/logs.ts: replace local fileSchema with mediaUserFileSchema (the established UserFile boundary schema with .passthrough()) - file-download.tsx: drop local FileData interface, use UserFile from @/executor/types * improvement(contracts): promote userFileSchema to primitives Move the canonical UserFile boundary schema out of tools/media/shared.ts (where it didn't belong — logs aren't media tools) into primitives.ts as userFileSchema. Update logs, stt, and video contracts to import from the shared primitive. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
98f8e854eb |
improvement(tables): extract TablesDetail wrapper, ship trigger followups (#4476)
* ui improvements * Update status pils, make checkbox column sticky * add Run workflow to context menu * Refactor dispatching logic * fix checkbox width to be smaller if csv is small * Add drag behavior for workflows, stop workflow on multi select * fix z index of checkbox to left, add view workflow button * Switch to emcn buttons for Add inputs * Split up workflow sidebar from column sidebar, refactor cells * Lint and add auto run toggle * fix column reordering, add action bar * Create and use emcn square * Reconcile post-merge: drop positionMap, use rowId-based selection Staging refactored Tables UI to decouple from DB position (gutter from array index, checkedRows keyed by rowId, no PositionGapRows). Bring HEAD's action-bar / context-menu helpers in line: contextMenuRowIds, selectedRowIds, actionBarRowIds now key off row.id and walk `rows` directly. Drop the maxPosition / positionMap derived state. Collapse COLUMN_SIDEBAR_WIDTH_CSS to a numeric COLUMN_SIDEBAR_WIDTH used by both the sidebar shell and the table's reserved padding-right. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(table): backfill remapped workflow outputs from execution logs When a workflow column is re-pointed to a different (blockId, path), populate its existing rows with the new output's value pulled from saved execution logs instead of leaving them empty until the next run. Rows where the new mapping has no logged value clear (matching the previous behavior for those rows), but rows where the workflow already has the new output's value surface immediately. Refactor backfillAddedGroupOutputs into a generalized backfillGroupOutputsFromLogs helper with an `overwrite` flag — used in both the added-outputs path (preserves hand-edited values) and the new remapped path (overwrites since the new mapping is the source of truth). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): update column type when remapping workflow output A remap that changes the output's leaf type (string → number, json → boolean, etc.) was leaving the column's declared type stale. The clear- then-backfill flow then failed schema validation on every row, so the backfill silently aborted and the column stayed empty. Resolve the new leaf type via flattenWorkflowOutputs + columnTypeForLeaf for each mappingUpdate, and patch schema.columns[i].type before the schema write. The clear-tx then backfill ordering now works end-to-end across type changes. If the workflow or its target output can't be resolved (workflow deleted, block removed), fall back to leaving the column type alone — the backfill will skip rows whose picked value doesn't match, same as before. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): stringify objects instead of "[object Object]" in cells If a column's declared type lags its row data (e.g. a workflow column mid-remap, where the schema cache hasn't refetched yet but the row data already has the new mapping's value), formatValueForInput and the cell-render text variant fell through to String(value) and rendered "[object Object]". JSON-stringify objects in both spots so the transient skew shows the actual data. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): drop extra left border on workflow group meta header The meta cell had border-r/b/l while regular headers have only border-r/b. With border-separate tables, that extra 1px left border shifted the meta cell's content one pixel right of the columns below it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): align workflow meta header without dropping its left border Restore border-l and pull the cell back -1px with -ml-px so the visible left border overlaps the previous cell's right border instead of adding 1px to the meta cell's box. Content lines up with the columns below. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): draw meta header left border via ::before pseudo Adding border-l to the meta cell shifted its content right by 1px because table-fixed + border-separate honors the border inside the colspan'd cell's width budget. -ml-px doesn't work on <th>. Render the visible left edge via a ::before at left: -1px instead — paints over the prior cell's right border without consuming any of the meta cell's content area. Content lines up with the columns below. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): add missing barrels, drop doubled-path imports Match the convention used by logs/components: every component folder exposes its public API via index.ts so consumers import from the folder name, not from its internal filenames. - New barrels: column-config-sidebar/, workflow-sidebar/, table-action-bar/, table/cells/, table/headers/. - Rename table-filter/index.tsx → index.ts (barrel is not a component). - Top-level components/index.ts re-exports every sibling folder so external consumers have one import path. - Replace `from '../foo/foo'` doubled paths in table.tsx with the shorter barrel-anchored form. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): introduce TablesDetail wrapper as thin passthrough Phase 1 step 0 of the wrapper extraction (see plan okay-lets-make-a-shimmying-trinket.md). page.tsx now renders TablesDetail, which today is a passthrough to <Table>. Subsequent commits lift surface state out of <Table> into this wrapper one piece at a time. The mothership chat path (<Table embedded>) is untouched — <Table> stays exportable as a lower-level component for embedded contexts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): lift slideout panel state into TablesDetail wrapper The three right-edge slideout panels (column config, workflow config, execution details) move out of <Table> into the wrapper. The wrapper owns a single useReducer that encodes the at-most-one-open invariant as a discriminated union — opening any one panel automatically closes the others. <Table> emits open requests via three new callback props. Also extract <ExecutionDetailsSidebar> from inline-in-table.tsx to its own folder so the wrapper can compose it cleanly. Update the embedded mothership callsite (resource-content.tsx) to render <TablesDetail embedded> instead of <Table embedded>. Phase 1 step 1 of the wrapper extraction. <Table> shrinks from 3849 → 3787 lines; <TablesDetail> grows from 19 → 145 lines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): lift delete-table modal + mutation into wrapper The delete-table confirmation modal and `useDeleteTable` mutation move out of <Table> into TablesDetail. <Table> exposes a new `onRequestDeleteTable` callback fired by the page-header Delete action. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): lift CSV import dialog into wrapper ImportCsvDialog moves out of <Table>. Grid exposes `onRequestImportCsv` fired by the page-header menu item; wrapper owns the open state and renders the dialog. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): lift RowModal (edit + delete) into wrapper Both RowModal instances move out of <Table> into the wrapper. Grid emits `onOpenRowModal(row)` (Space key) and `onRequestDeleteRows(snapshots)` (context menu). Post-delete cleanup (push undo, clear selection) needs grid-internal state, so the grid populates an `afterDeleteRowsSinkRef` callback that the wrapper's modal `onSuccess` invokes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): lift delete-columns modal into wrapper The destructive delete-columns confirmation modal moves into the wrapper. Grid emits `onRequestDeleteColumns(names)`; the cascade itself (per-column mutation, undo push, columnOrder + columnWidths cleanup) stays in the grid as a sink the wrapper invokes on confirm — too grid-internal to lift cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): lift run/stop mutations + TableActionBar to wrapper useRunGroup and useCancelTableRuns move out of <Table> into the wrapper, along with the <TableActionBar> render. Grid receives onRunGroup, onRunRows, onStopRow, onStopRows, onStopAll, and cancelRunsPending as props — used by the per-row gutter Play/Stop, the workflow-group meta-cell run menu, and the right-click context menu's Run/Stop on selection items. Action-bar selection state (actionBarRowIds, runningInActionBar, hasWorkflowColumns) is derived from grid-internal state, so the grid emits a `SelectionSnapshot` via `onSelectionChange` from a useEffect. Wrapper uses the snapshot to drive the floating <TableActionBar>. Phase 2 step 1 of the wrapper extraction. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): lift queryOptions to wrapper queryOptions (filter + sort) moves out of <Table> into the wrapper, making it a single source of truth that drives one useTable call. The wrapper passes the bundle down to the grid; sort/filter handlers in the grid call onQueryOptionsChange. Eliminates the previous double-useTable pattern (one for the grid's filtered/sorted view, one in the wrapper's hardcoded null/null query for sidebar metadata). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): lift page header (breadcrumbs/options/filter) to wrapper Phase 3 of the wrapper extraction. The full page-header surface moves out of <Table>: - ResourceHeader (breadcrumbs, table-rename UI, headerActions, createTrigger) - ResourceOptionsBar (sort + filter toggle) - TableFilter (filter panel — wrapper owns filterOpen state) - RunStatusControl (in the leading actions when runs are active) useRenameTable + useInlineRename for the breadcrumb name move to the wrapper. The grid populates pushTableRenameUndoSinkRef so the rename is still part of the grid's undo stack. Extract NewColumnDropdown and RunStatusControl from inline-in-table.tsx to their own folders so the wrapper composes them cleanly without reaching into the grid's internals. Hoist generateColumnName from grid-internal useCallback to a shared util so both the page-header and inline-header NewColumnDropdowns use the same logic. After this lift <Table> is the data grid only — no page surface, no modals, no slideouts, no breadcrumbs. The selection snapshot now includes totalRunning so the wrapper can render the page-header RunStatusControl from outside the grid. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(tables): cleanup pass on TablesDetail wrapper extraction Six-pass cleanup against the wrapper extraction diff: - Effects: add content-compare bailout to onSelectionChange emit so unchanged snapshots don't churn wrapper re-renders. - Memos: drop unnecessary activeSortState memo, fold into sortConfig. - Callbacks: remove ~10 useCallbacks with no observed reference (sidebars not memoized, modals not memoized, inline arrows on non-memoized children); keep the ones that feed into <DataRow>/<RunStatusControl>/ <ResourceHeader> (memoized) or grid-side useCallback deps. - Dead props: drop onQueryOptionsChange/onRequestDeleteTable/ onRequestImportCsv from <Table> — the page-header lift made them unused but the props weren't removed. - React Query: drop redundant tableWorkflowGroupsRef (created when onRunRows was useCallback-wrapped; after callback cleanup it can read the query data directly). - emcn: normalize Loader sizing to h-[14px] w-[14px] to match the codebase convention. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): re-seed columnOrder when columns change server-side The metadata-seed effect short-circuited after the first seed, so any later schema change (e.g. adding a workflow output column) couldn't push the new column into local columnOrder. The new column would then fall into the "remaining" bucket of `displayColumns` and render at the end of the table — until the user refreshed and the grid re-mounted with the now-current metadata. Drop the `metadataSeededRef.current` short-circuit from the early return so the effect can also reach the after-first-load re-seed branch, which already does the right thing (only re-seeds when the set of columns changes, leaves pure-reorder cases alone). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(tables): rename wrapper to <Table>, grid to <TableGrid> Match the naming convention used elsewhere in the workspace (workflow.tsx → <Workflow>, base.tsx → <Base>, logs.tsx → <Logs>). - tables-detail.tsx → table.tsx (exports <Table>) - components/table/ → components/table-grid/ (exports <TableGrid>) - components/table-grid/table.tsx → table-grid.tsx - Drop <ExecutionDetailsSidebar> — was a 3-line passthrough (executionId → useLogByExecutionId → <LogDetails>); inline directly into table.tsx where it's used. - Flatten components/run-status-control/ folder to a single components/run-status-control.tsx file. 25-line single-use component with no internal subdirs — folder was overhead. Matches knowledge's max-badge.tsx precedent. Net: 1 wrapper rename + grid rename + 2 folder collapses, all imports updated. The mothership chat callsite updates from <TablesDetail embedded> to <Table embedded>. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): don't show "Waiting" for autoRun=false workflow groups A workflow group with autoRun=false never fires from the scheduler — the cell stays empty until the user clicks Run manually. Treating empty cells as "Waiting" misleads the user into thinking the group will auto-fire once deps are filled, which it won't. Skip autoRun=false groups when computing the per-row waiting labels so their cells render the empty-dash instead of the Waiting pill. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(copilot): regenerate tool catalog from copilot dev (#247) Pulls in the workflow_group operations on user_table: add_workflow_group / update_workflow_group / delete_workflow_group / add_workflow_group_output / delete_workflow_group_output / run_workflow_group, plus the autoRun / blockId / dependencies / groupId parameters and a tightened mapping description for import_file. Also picks up biome import-order fixes from `bun run lint`. * improvement(table): action bar in mothership + per-execution mode Three related improvements to the table action bar: 1. Reposition from `position: fixed` to `position: absolute` inside the table's container. Fixed-positioning anchored to the viewport, which centered the bar across the whole window instead of the table panel — wrong in mothership embedded view, where the table sits in the right half. Absolute scopes the bar to the table's bounds. 2. Show the bar for single-execution highlights — when the user selects one workflow-output cell, or 1 row × N cols all within the same workflow group. The bar enters per-execution mode with Run / Stop / View execution buttons targeting that one cell or group. 3. Skip View execution for cancelled cells. A cancelled cell may have been cancelled before the worker ever picked the job up, so its executionId can't be relied on. Tighten the gate everywhere (context menu + action bar) to only `completed` / `error` / `running`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): backfill on add_workflow_group_output, don't re-run addWorkflowGroupOutput (the one-shot single-output add path used by the copilot user_table tool) was calling triggerWorkflowGroupRun({ mode: 'all' }) after appending the output — that re-fired the workflow on every row. Trace a307ed8fd5fe2d931aa84dedab5a60f0 shows ~75 workflow-group-cell jobs enqueued in the seconds after a single add_workflow_group_output call. Replace with backfillGroupOutputsFromLogs (overwrite: false), the same flow updateWorkflowGroup uses when receiving newOutputColumns. Reads each row's saved trace spans and writes the new output's value back — no compute beyond a JSONB write per row, no double-billing the user for runs they didn't ask for. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): drop sql.raw quote-escaping in column-name interpolation Six call sites in lib/table/service.ts built JSON-key string literals at runtime via `sql.raw(\`'\${name.replace(/'/g, "''")}'\`)` for use with PostgreSQL's `data->'key'` / `data->>'key'` operators. Practically safe (NAME_PATTERN gates column names to alphanumeric+underscore at insert time) but a smelly pattern that breaks the moment validation loosens. Both `data->` and `data->>` accept a parameterized text value as the key, so the `sql.raw` is unnecessary. Replace each with a normal `${name}::text` binding. No behavior change; eliminates the manual quote-escaping surface. Affected sites: renameColumn (the data-rewrite UPDATE), upsertRow's match filter, updateColumnType's IS-NOT-NULL gate, updateColumnConstraints' required-check + unique-duplicate-check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(copilot-tool): forward autoRun + mappingUpdates on update_workflow_group The sim-side service and contracts already accept both fields, but the copilot tool's update_workflow_group handler was dropping them on the floor. Now `args.autoRun` (toggle the persisted auto-fire flag) and `args.mappingUpdates` (per-output (blockId, path) swap) get forwarded through to updateWorkflowGroup. Pairs with the upcoming copilot-side change that exposes these in the tool catalog JSON / Go handler / prompting (see copilot branch redo-workflow-tools). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(table): keep gutter border visible when hovering Run-row button The per-row Run button sat flush against the row-gutter cell's right border. Its hover background (rounded-rect surface-2) painted over the border line for the 20px height of the button, making the gutter divider appear to disappear at the hovered row. Add mr-px to the button so the hover bg stops 1px short of the cell's right edge, leaving the divider intact. * fix(table): unify auto-fire and manual run paths in scheduler scheduleWorkflowGroupRuns now owns eligibility, autoRun semantics, dep evaluation, and enqueue for both paths. Auto-fire callers omit opts; manual callers (triggerWorkflowGroupRun) pass { groupId, isManualRun: true } to bypass the autoRun=false skip and (for autoRun=false groups) the dep check. Per-row /run-workflow-group route delegates to triggerWorkflowGroupRun with rowIds=[rowId]. Single server-side path for both manual entry points. Also: optimisticallyScheduleNewlyEligibleGroups skips autoRun=false groups so editing a row's data doesn't phantom-mark autoRun=false output cells as Queued. * fix(table): render empty cells as blank, not em-dash Empty cells (any column type) showed an em-dash placeholder. Drop it so empty cells render blank — matches what the user expects when nothing's there. * fix(table): per-row Run fires autoRun=false groups regardless of deps handleRunRow filtered out every group whose deps weren't satisfied, which silently dropped autoRun=false groups (since their deps usually aren't satisfied — that's the whole point of autoRun=false). Click Run row, the autoRun=false group's cells stayed empty. Mirror the scheduler's semantics: autoRun=false bypasses the dep check, autoRun=true still requires deps. * fix ui shape * improvement(table): collapse run ops into run_column, derive action-bar buttons from selection The action bar now reflects what's actually selected: - Selection-driven scope (cells the user highlighted, not their full rows) - Play visible when there's anything empty/failed; Refresh when there's anything completed; both for mixed - run_cell / run_row deleted; everything funnels through run_column - Per-row gutter Play, right-click "Run workflows on N rows", and column-header menu all share the canonical run path - Shared RunMode type from the contract; cleanup pass via /simplify (readExecution / isExecInFlight reuse, runScope helper, flat onViewExecution prop) * chore(copilot): regen tool catalog after dropping run_cell / run_row + dependencies.workflowGroups Mirror the copilot-side catalog change so the generated TS catalog matches the deployed copilot tool surface. * fix(table): atomic per-key writes for executions, plus run-op race fixes The executions blob on user_table_rows was read-modify-written wholesale on every update. Concurrent writers (a column edit and a manual-retry stamp, two pickup calls, a cancel and a cascade) each computed a merge from their own snapshot, and the last writer clobbered keys it never touched — producing stuck "queued" cells, vanished stamps, and stale completed exec records reappearing after retries. Fixes: - updateRow / batchUpdateRows now apply executionsPatch via a SQL jsonb merge expression. Each writer only mutates the keys it explicitly patches; other keys are preserved. Eliminates the cross-key clobber. - writeWorkflowGroupState bypasses the stale-worker guard for `queued` (new scheduler stamp) and `cancelled` (authoritative cancel) writes — those ARE the new authority for the cell. Previously the new run's stamp was being rejected by the same guard meant to block the OLD worker's writes. - skipScheduler flag on UpdateRowData / BatchUpdateByIdData lets the cancel path and runWorkflowGroupsInternal opt out of the implicit auto-fire pass (cancel was waking up siblings; manual-run was racing its own scheduler). - CELL_CONTENT pinned to h-[22px] so status badges don't grow rows. * chore(table): remove table-row sockets, both sides Tables don't use realtime sockets in prod — strip the dead path so we stop paying the per-row HTTP forward + socket emit on every cell write. Polling on running execs already covers reconciliation. Sim side: - service.ts: drop notifyTableRowUpdated/Deleted, notifyTableDeleted, the postRealtimeBridge helper, and all callsites. - hooks/queries/tables.ts: drop the socket subscription block in useTableRows; poll-on-running stays. Remove useEffect / useSocket imports. - app/.../tables/[tableId]/hooks/use-table.ts: drop the merge-on-event useEffect and unused imports. - app/workspace/providers/socket-provider.tsx: drop joinTable/leaveTable, onTableRowUpdated/Deleted/onTableDeleted, currentTableId state, related events + types. Realtime side: - handlers/tables.ts deleted; index.ts no longer wires it. - routes/http.ts: drop /api/table-row-updated, /api/table-row-deleted, /api/table-deleted endpoints. - rooms/{memory,redis}-manager.ts: drop emitToTable, handleTableRowUpdated/ Deleted, handleTableDeleted, related imports. - rooms/types.ts: drop method declarations, TableRowUpdatedPayload type, tableRoomName helper. - middleware/permissions.ts: drop unused verifyTableAccess. Bonus from parallel work: - cell-content typewriter trigger refinement. * fix(table): clearing a workflow output cell also clears its exec record When the user wipes a workflow output column value, the auto-fire reactor needs to be re-armed for that group. Previously, a stale cancelled / error exec record blocked the eligibility predicate (gate at line 79 hard-rejects those statuses on auto-fire) and the cell stayed stuck in its old terminal state — visible as "Cancelled" cells that wouldn't re-run no matter what. Both updateRow and batchUpdateRows now derive an `executionsPatch[gid] = null` for any output column the patch sets to empty. The data clear and the exec clear ride the same SQL transaction, so the row never lands in a stale- status-with-empty-data state. Symmetric to how `completed` already worked via `areOutputsFilled` in the predicate — clearing the cell wins over the prior exec status, regardless of what that status was. (Also revert typewriter-trigger experiment from a parallel session that was in-progress on this branch.) * fix(table): waiting state, optimistic UX, schema-mutation polling, exec cleanup A bundle of small UX + correctness fixes around workflow-cell run state. cell-render.tsx - In-flight (queued/running/pending) now wins over the existing value, so re-runs surface immediately instead of looking like nothing happened until the worker writes the new value. - "Waiting on X" wins over a stale `cancelled` / `error` exec when deps are unmet — clearing a dep now reads as actionable instead of stuck. useRunColumn (hooks/queries/tables.ts) - onSettled now cancels in-flight polls before invalidating. Stops a poll that landed mid-mutation from clobbering the optimistic state with stale data, which produced the queued → cancelled → queued flicker. addWorkflowGroup / updateWorkflowGroup (autoRun toggle on) - Awaits scheduleRunsForTable instead of fire-and-forget. The route returned before the queued exec stamps committed, so the post-mutation refetch saw no in-flight cells and polling never started — cells looked stuck even though the server eventually stamped them. deleteColumn / deleteColumns - Strip orphaned executions[gid] keys when deleting a column orphans its parent group. Without this, stale running/queued exec records lingered on every row forever and inflated the page-header "N running" counter even on tables with no actually-running cells. UI - Action-bar leading label: "Selected N workflow cell(s)". - Context menu: Run / Refresh items mirror the action bar's Play / Refresh split, gated on the same selection-status flags so both surfaces show the actions that match the current state. * refactor(table): consolidate exec-status helpers + fix N-running counter Cleanup pass on the recent table changes — pulls duplicated predicates and SQL snippets into shared helpers and fixes one drift bug along the way. - isExecInFlight: now single export from lib/table/deps.ts. Removed the duplicate in components/table-grid/utils.ts. Used by isGroupEligible (server eligibility) and runningByRowId (client counter). - isOptimisticInFlight: kept local to hooks/queries/tables.ts — renamed from isInFlight to disambiguate from the stricter isExecInFlight. The two predicates differ on `pending` without a jobId: optimistic patches and poll-trigger want the broader version, eligibility wants the strict one. - areOutputsFilled: single export from lib/table/deps.ts, dropped duplicate from workflow-columns.ts. - classifyExecStatusMix: shared row × group walker in table-grid/utils.ts. Replaces two copies of the same loop in table-grid.tsx (selectionStats + contextMenuStats). Both surfaces now have the same short-circuit semantics, including the seen-all-selected-rows early break that contextMenuStats was missing. - stripGroupExecutions: SQL helper in service.ts. Replaces three copies of the `UPDATE user_table_rows SET executions = executions - $gid::text` pattern across deleteColumn / deleteColumns / deleteWorkflowGroup. Drift bug: - runningByRowId / totalRunning counted only `running` and `queued`. Every other in-flight check in the codebase treats post-stamp `pending` as in-flight too, so the page-header "N running" badge briefly dropped to 0 between scheduler stamp and worker pickup. Now uses isExecInFlight. * fix(table): address pr review (drop dead workflowNameById prop, reset didDragRef on dragend, align sidebar width) * fix(table): scope post-clear schedule to targeted groups, forward mode Multi-group manual runs (Run row, gutter Play, action-bar Play across mixed completed + cancelled cells) re-fired completed-and-filled siblings. runWorkflowGroupsInternal cleared only the groups it filtered, then called scheduleRunsForRows with isManualRun: true and no group / mode filter — so the post-clear pass walked every group on the table with default mode 'all', and any autoRun=true completed sibling whose deps were satisfied got queued again. Scope the post-clear call to targetGroups and forward mode. * fix(table): meta-cell drag-leave flicker guard + plumb unique on create * fix(table): strip sibling deps when removing workflow output via updateWorkflowGroup deleteWorkflowGroup already stripped removed-column deps from sibling groups, but updateWorkflowGroup (the path the UI takes when deleting one output of a multi-output group) didn't — schema validation then rejected the update with 'Group X depends on missing column Y'. * improvement(table): debug logs at every cascade decision branch * improvement(table): parallelize queued-stamp writes within concurrency-cap chunks * Simplify stripping column names * fix lint, ci --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
ec5793fbaf |
fix(billing): drop transaction wrapper in recordUsage to relieve pool contention (#4494)
* fix(billing): drop transaction wrapper in recordUsage to relieve pool contention * fix(billing): always warn on userStats drift in recordUsage |
||
|
|
49713f887f | fix(type-error): subblock migrations type error (#4492) | ||
|
|
09425553b3 |
fix(sanitize): repair malformed subblock states (#4490)
* fix(sanitize): repair malformed subblock states * address comments * address comment |
||
|
|
76d602fed5 |
fix(workday): correct SOAP service routing and reference types (#4485)
* fix(workday): correct SOAP service routing and reference types - create-prehire: route Put_Applicant to Recruiting service (was Staffing, where the operation does not exist) - assign-onboarding: use WID for Action_Event_Reference (was Background_Check_ID, wrong identifier domain for hire events) - update-worker block: rewrite labels and wand prompt to match Change_Personal_Information demographic-only scope (prior prompt instructed LLM to emit businessTitle/primaryWorkEmail which the SOAP op rejects) - enrich opaque JSON output descriptions on worker, workers, organizations, compensationPlans * fix(workday): correct Date_of_Birth casing in update wand prompt |
||
|
|
28e60bfd4e |
fix(docker): drop scripts/ from workspaces array (#4484)
`turbo prune sim --docker` strips `scripts/` from the pruned output (sim doesn't depend on it), but the pruned root package.json still listed it as a workspace, causing `bun install` to fail with "Workspace not found 'scripts'" in the Docker build. scripts/ is dev-only tooling that runs from the repo root via `bun run scripts/*.ts`. Its imports (glob, yaml) resolve against the root node_modules — they're already in root devDependencies. - Remove "scripts" from root workspaces array - Delete scripts/package.json (no longer a workspace, manifest unused) Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
28f1912e89 |
feat(files): zoom controls for inline mermaid and images in markdown (#4411)
- Add pan/zoom/fit controls to mermaid diagrams rendered inline in markdown — same experience as the standalone .mmd viewer - Wrap inline markdown images in ZoomablePreview with fit-to-container scale - Allow fit zoom to upscale small diagrams to fill the view (previously capped at 100%) |
||
|
|
a251e45400 |
feat(sap): add SAP Concur integration block and SAP S/4HANA validation fixes (#4483)
* feat(sap): add SAP Concur integration block and SAP S/4HANA validation fixes
* added
* fix(sap_s4hana): preserve raw Set-Cookie array for CSRF cookie join
SecureFetchHeaders previously collapsed multi-value Set-Cookie headers
with ", ", forcing consumers to re-split via a fragile regex. Cookie
values containing "=" or "," (e.g., Base64 session tokens) could be
misparsed and produce malformed Cookie strings on CSRF-protected
mutations.
Add SecureFetchHeaders.getSetCookie() that returns the raw array, and
update the S/4HANA OData proxy's joinSetCookies to consume it directly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap-concur): rename misleading exchange-rate tool, drop unusable refresh_token grant, validate geolocation host
- Rename sap_concur_get_exchange_rate to sap_concur_upload_exchange_rates (POST bulk upload, not GET)
- Remove refresh_token from SapConcurGrantType / Zod enum / block dropdown / docs (no implementation)
- Validate Concur geolocation hostname against SAP_CONCUR_ALLOWED_DATACENTERS
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* finished
* docs
* fix(docs): escape braces in tool/trigger description prose for MDX
Tool and trigger descriptions can contain URL path placeholders like
{reportId} or JSON-shape hints like { Items, NextPage }. When rendered
as MDX prose (not table cells), these were emitted unescaped and MDX
parsed them as JSX expressions, failing prerender with
"ReferenceError: reportId is not defined".
Escape { and } in the operation-level description and trigger
description renderers, matching the existing escaping in table-cell
descriptions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap-concur): align with live API on travel-profile, itineraries, and context types
- list_travel_profiles_summary: rename Status query to Active with 1/0 values, tighten LastModifiedDate format hint
- list_itineraries / get_itinerary: use documented userid_type / userid_value / ItemsPerPage / Page query keys
- create_report_comment: contextType allows MANAGER (move to EXPENSE_READ_CONTEXT_TYPE_OPS)
- get_list_item: drop unused listId from block (tool only needs itemId)
- Tighten description copy on list_expenses/get_itemizations/associate_attendees/remove_all_attendees
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap-concur): correct Cash Advance v4.1 paths, add SCIM filter param
- Update Cash Advance create/get/issue tools from /cashadvance/v4/ to /cashadvance/v4.1/ to match the live API
- Add filter query param to list_users (SCIM v4.1 supports filtering by userName, employeeNumber, externalId)
- Regenerate docs MDX
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap-concur): drop SCIM list_users filter param (not supported on v4.1 GET)
SCIM Identity v4.1 GET /Users does not accept a filter query parameter — filtering
is only supported via POST /Users/.search (already exposed by sap_concur_search_users).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sap-concur): final live-API alignment
Verified against live SAP Concur docs (concur/developer.concur.com preview branch):
- Revert Cash Advance paths to /cashadvance/v4/ (v4.1 endpoints do not exist; live spec is v4)
- Travel Profile v2 summary has no Active/Status query param — drop the filter from tool, types, and block
- Report Comments v4 contextType is TRAVELER or PROXY only (NOT MANAGER) — move create_report_comment + list_report_comments into the TRAVELER/PROXY context group
- Trip v1.1 query keys: userid_type / userid_value / ItemsPerPage / Page (snake/Pascal per docs) — already correct, kept
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* docs
* fix(sap-concur): restore Cash Advance v4.1 paths
Re-verified against live developer.concur.com docs at /api-reference/cash-advance/v4-1.cash-advance.html — only v4.1 endpoints are documented:
- POST /cashadvance/v4.1/cashadvances
- GET /cashadvance/v4.1/cashadvances/{cashAdvanceId}
- POST /cashadvance/v4.1/cashadvances/{cashAdvanceId}/issue
The /cashadvance/v4/ docs page returns 404. Reverts the prior local rollback in
|
||
|
|
7953c56aca |
fix(security): xlsx CVE bump and bundled security hardening (#4481)
* fix(security): xlsx CVE bump and bundled security hardening * fix(stripe): use configured secret key for SDK init Avoids leaving a recognisable placeholder string in heap dumps and error serialisations. Webhook verification remains a purely local HMAC operation; the SDK's constructor key is unused by it. Addresses Greptile feedback on #4481. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(stripe): use static Stripe.webhooks for verification Avoids instantiating a Stripe client just to access constructEvent. The webhook signing secret is per-trigger (user-provided whsec_…) and unrelated to our billing STRIPE_SECRET_KEY, so coupling them was wrong. Stripe.webhooks is exposed as a static — no client, no API key needed. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(ci): revert client-bundled tools to avoid .server import in client * fix(security): collapse 403 to 404 on v1 detail-by-ID routes * chore(security): remove unused validateAgiloftInstanceUrl helper * fix(security): bump minimatch + clean up scripts/ workspace Resolves CVE-2026-27903 (GHSA-7r86-cg39-jmmj) by adding a root-level minimatch ^10.2.5 override. Also resolves CVE-2026-0969 in next-mdx-remote (bumped to ^6.0.0). Cleanup: - Make scripts/ a proper bun workspace (root workspaces array) - Remove duplicate scripts/package-lock.json (this repo uses bun) - Remove redundant scripts/bun.lock (now hoisted to root) - Remove vestigial scripts/setup-doc-generator.sh - Slim scripts/package.json to its real deps (glob, yaml) - Gitignore stray package-lock.json files - Update scripts/README.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
00c424baa9 |
improvement(executor): reserved keyword errors (#4482)
* improvment(executor): reserved keyword errors * address comments and make error messages for func execute make sense block ref accs |
||
|
|
690b7abb6a |
improvement(seo): restore explicit AI/search bot allow-list and add link-preview rules (#4480)
* improvement(seo): restore explicit AI/search bot allow-list and add link-preview rules * fix(seo): correct xAI UA strings, drop Bravebot, block /playground/ and /w/ from link-preview bots * fix(seo): drop unverified Grok UAs, correct DeepSeekBot and ImagesiftBot tokens * fix(seo): re-add Bravebot to allow-list per Brave Search docs * improvement(seo): drop redundant named AI/search bot allow-list * chore(seo): trim verbose comments in robots.ts |
||
|
|
369f9b613d |
fix(office-excel): support Office.js add-in embed and surface Graph errors (#4479)
* fix(office-excel): support Office.js add-in embed and surface Graph errors * fix(office-excel): delegate to parseGraphErrorFromData and handle array embed param |
||
|
|
79ffccc140 |
feat(emailbison): block, tools, sharepoint v2 block with cleaner code (#4470)
* feat(emailbison): block, tools * type improvments * typecheck issue * add email bison trigger, cleanup sharepoint block * address comments * fix tests * error on partial upload failures |
||
|
|
bfd0f46119 |
improvement(next): bundle and CI cache config (#4478)
- drop redundant turbopack config (Next 16 defaults) - remove lucide-react/date-fns from optimizePackageImports (built-in defaults) - enable turbopackFileSystemCacheForBuild for warm CI builds - disable poweredByHeader - swap actions/cache for Blacksmith sticky disk on .next/cache |
||
|
|
6d4ffff327 |
fix(agiloft): correct response parsing, add EWGetChoiceLineId tool (#4477)
* fix(agiloft): correct response parsing, add EWGetChoiceLineId tool * fix(agiloft): address PR review feedback |
||
|
|
48331451b0 |
chore(deps): upgrade next.js to 16.2.4 (#4460)
* chore(deps): upgrade next.js to 16.2.4 - Bump next and @next/env to 16.2.4 across root, apps/sim, apps/docs - Replace next-runtime-env's env() helper (calls unstable_noStore(), rejected by Next 16.2 outside request scope) with a direct window.__ENV / process.env getter - Add export const dynamic = 'force-dynamic' on landing /privacy and /terms pages so NEXT_PUBLIC_* runtime env reads aren't baked at build * fix(whitelabel): force dynamic rendering for manifest.ts Without this, NEXT_PUBLIC_BRAND_* values are baked into the manifest at build time. Pairs with the next-runtime-env removal in the prior commit, restoring Docker runtime injection for whitelabel deployments. * fix(oauth): wrap consent page useSearchParams in Suspense Next 16.2's stricter prerender check fails the build when useSearchParams() is used without a Suspense boundary. Splits the client component into an outer wrapper and inner body. * fix(whitelabel): force dynamic rendering for landing segment Client components in (landing) (e.g. Navbar) read NEXT_PUBLIC_BRAND_* via getEnv. Without this, SSR prerender would bake the build-time process.env values into HTML, mismatching window.__ENV after hydration in Docker runtime-env deployments. Cascades to all landing routes via the layout. * revert(whitelabel): drop force-dynamic from landing layout Cascading force-dynamic neutered dynamicParams = false + generateStaticParams on /blog/[slug], /integrations/[slug], /models/[provider], /models/[provider]/[model] — killing static prerender for SEO-critical pages. The hydration concern only materializes for whitelabel Docker deployments where build-time and runtime NEXT_PUBLIC_BRAND_* differ; those deployments can set the vars at build instead. Keeping force-dynamic on /privacy, /terms, and /manifest where it actually matters. * fix(prerender): wrap useSearchParams callsites for Next 16.2 Next 16.2 fails the build when a client component using useSearchParams() is statically prerendered without a Suspense boundary. - Wrap landing Navbar in Suspense (imported by /oauth/consent and other pages) - Add force-dynamic to reset-password, invite/[id], and unsubscribe pages whose client bodies call useSearchParams * fix(navbar): preserve SSR HTML, drop Suspense bailout Reading useSearchParams() forced a Suspense fallback that emitted no navbar HTML during SSR — leaving crawlers and no-JS users without nav. The 'home' query param only affects client-side link targets, so read it from window.location in an effect after hydration. Restores full SSR navbar markup. * chore: trim verbose comments in next.js upgrade The force-dynamic export name is self-documenting; the remaining env.ts comment is tightened to the essential WHY (why we don't use next-runtime-env's helper). |
||
|
|
ad88859d6e | chore(skills): add /add-model and /validate-model commands (#4475) | ||
|
|
5d38222a14 |
fix(function): validate custom tool param keys before code interpolation (#4474)
* fix(function): validate custom tool param keys before code interpolation * fix(function): exclude JS reserved words from param key injection guard |
||
|
|
a945399c53 | feat(models): add grok-4.3 (#4472) | ||
|
|
1989a12ff3 | improvement(func-exec): normalize inputs to match schema (#4473) | ||
|
|
7b6aa728ae |
improvement(resolver): use context variables for block outputs in function block code (#4223)
* 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: use context variables for block outputs in function block code When a function block references another block's output via <BlockA.result>, the executor previously embedded the full value as a JavaScript literal directly in the code string. For large outputs (>50 KB), this caused the code string to exceed the terminal console display limit, making inputs appear truncated or replaced with { __simTruncated: true } in the UI. Instead, block output references in function block code are now stored as named global variables (__blockRef_N) in the isolated VM context. The code string only contains the compact variable name, keeping it small regardless of the referenced value size. Loop/parallel/env/workflow references are still inlined as literals since the API route has no way to resolve them independently. The _runtimeContextVars key is filtered from sanitizeInputsForLog so it does not appear in execution logs or SSE events. Pre-resolved context variables are merged with any variables produced by the API route resolveCodeVariables, with executor values taking precedence. Fixes #4195 * fix: address Cursor and Greptile bot review comments - Pass preResolvedContextVariables through to shellEnvs for Shell language (Cursor: shell loses pre-resolved block refs, executes against undefined vars) - Remove duplicate CodeExecutionOutput interface declaration (Cursor + Greptile: dead duplicate declaration in tools/function/types.ts) - Deduplicate identical block references in resolveCodeWithContextVars so the same <BlockA.result> reused multiple times shares one __blockRef_N slot (Greptile P2: avoid duplicating large payloads across the wire) * fix: shell block references and complex env value serialization Two follow-ups to the function-block context-variable refactor: - resolveCodeWithContextVars now emits `$__blockRef_N` for shell function blocks so the script dereferences the env var injected by the executor. Other languages still receive the bare identifier. - The function-execute route now JSON-stringifies non-primitive values when building shell env vars, replacing the previous `String(v)` call that produced `[object Object]` for objects/arrays. Co-Authored-By: Octopus <liyuan851277048@icloud.com> * fix lint * review pass * ignore shell comments * update contract * fix tests --------- Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Theodore Li <theodoreqili@gmail.com> Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: octo-patch <octo-patch@github.com> Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai> |
||
|
|
ae87481d83 |
fix(data-drains): convert unique-name violations to 409 on POST/PUT (#4471)
Catch Postgres 23505 on insert/update so concurrent name conflicts return a clean 409 instead of a 500. The data_drains_org_name_unique index already prevents duplicate rows; this just improves the UX. |
||
|
|
a24e851859 |
fix(mothership): enforce ownership check on workflow resource attachments (#4468)
* fix(mothership): enforce ownership check on workflow resource attachments * fix(mothership): fix table and knowledgebase BOLA in resource attachment resolution * fix(mothership): apply workspace scope to table in processContextsServer * fix(mothership): verify workspace membership before resolving workspace branch * fix(data-drains): use const for timeoutId in sleepUntilAborted * fix(test): mock db.select and drizzle and for workspace permissions check * fix(mothership): always derive workspace from workflow record in workflow branch |
||
|
|
1814105709 |
refactor(tables): row selection as discriminated union (#4466)
* fix(tables): decouple master checkbox from cell-range, add allRowsSelected flag
Master checkbox detached from gutter selection state when rows or columns
changed after Cmd+A: the predicate matched normalizedSelection bounds
exactly (endRow === rows.length-1, endCol === displayColumns.length-1),
so any post-selection growth flipped it false while the cell-range
overlay still painted every row checked.
Replace the structural two-branch predicate with an explicit
allRowsSelected flag plus a uniform set-membership check. handleSelectAllRows
sets the flag in O(1); handleRowToggle materializes checkedRows when
toggling out of "all" mode. Bulk-op read sites (delete, copy, cut,
selectedRowCount) honor the flag.
Decouple gutter checkbox from cell-range drag: dragging cells no longer
fills gutter checkboxes — they reflect explicit row-selection intent
only, matching Sheets/Airtable. Cell-range overlay still paints cells.
* refactor(tables): row selection as discriminated union
Collapse `checkedRows: Set<string>` + `allRowsSelected: boolean` into a
single `RowSelection = { kind: 'none' | 'some' | 'all' }`. Impossible
states (all + non-empty Set) become unrepresentable; predicates like
`rowSelectionIncludes` and `rowSelectionIsEmpty` replace ad-hoc checks at
every read site.
* fix(tables): clear row selection after context-menu delete
handleContextMenuDelete dispatched the delete but left rowSelection at
its prior 'all' or 'some' state. After rows clear and a new row arrives
(realtime, undo, append), rowSelectionIncludes returned true for it,
rendering it checked and flipping the master checkbox back on.
* chore(tables): address review nits on row selection refactor
- guard selectedRowCount 'all' branch on contextRow membership in rows
- restore blank line between row-selection helpers and constants
* chore(tables): rename rowSelectionChanged to cellRangeRowChanged
The helper compares NormalizedSelection (cell-range) state for a given
row, not RowSelection. The old name collided with the new row-selection
discriminated union and read ambiguously.
* fix(tables): guard context-menu delete on stale rows, preserve selection on cancel
- Guard the kind='all' branch on contextRow membership in currentRows
(matches the same fix applied to selectedRowCount), so a context menu
on a stale row no longer deletes the entire table.
- Drop the eager rowSelection clear at modal-open time. The modal's
onSuccess already calls handleClearSelection after the mutation
resolves, so the post-delete invariant still holds; if the user
cancels, the selection is now preserved.
|
||
|
|
80eb5b9a6e |
fix(security): block IPv4-compatible IPv6 SSRF bypass (#4467)
* fix(security): block IPv4-compatible IPv6 SSRF bypass * fix(security): also block IPv4-compatible IPv6 with Class E embedded IPv4 * fix(security): correct RFC1918 test label for IPv4-compat IPv6 |
||
|
|
93c0202c30 |
fix(md): file streaming patch preview (#4465)
* fix(md): file streaming patch preview * address comment |
||
|
|
3a7928987e |
improvement(confluence): expand scopes, persist canonical mode toggle (#4461)
* improvement(confluence): expand scopes, persist canonical mode toggle * improvement(confluence): memoize persisted canonical modes parse * fix(confluence): paginate space selector dropdown Confluence v2 spaces endpoint caps at limit=250 per page. The selector endpoint was making one request and silently dropping every space past the first page, which is why some spaces only worked when entered as a manual spaceKey. Now follows _links.next cursor up to 20 pages (5000 spaces). * fix(confluence): include archived spaces in selector dropdown Confluence v2 /spaces defaults to status=current and the status param is a single-value enum, so archived spaces never surface. They synced fine when entered manually as a spaceKey because the connector looks up spaces via ?keys=<key> which ignores status. Now fetches current and archived in parallel and tags archived ones in the dropdown label. * improvement(confluence): stream paginated space selector results Bake pagination support into the selector abstraction via an opt-in fetchPage definition so dropdowns populate progressively instead of blocking on a full page-walk. Confluence spaces now stream current then archived in a single cursor sequence. |
||
|
|
cef351fa25 |
fix(terminal): terminal console update for child spans + hitl state machine (#4450)
* fix(terminal): terminal console update for child spans" * address comments * fix hitl state machine * address comments * address greptile |
||
|
|
d721dc3358 |
feat(enterprise): add data drains for continuous export to S3 / webhook (#4440)
* feat(enterprise): add data drains for continuous export to S3 / webhook * chore(data-drains): regenerate migration on top of staging + bump route baseline Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-drains): clarify retention pairing is user-coupled, not enforced Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(data-drains): preserve explicit forcePathStyle=false + reserve x-sim-signature Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(data-drains): drift guard ensures every webhook header is reserved Asserts that any header buildHeaders writes is rejected when reused as a custom signatureHeader. Adding a new metadata header without mirroring it into RESERVED_SIGNATURE_HEADER_NAMES now fails CI. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
d517415c77 |
chore(docs): upgrade fumadocs to latest minor versions (#4462)
* chore(docs): upgrade fumadocs to latest minor versions - fumadocs-core: 16.6.7 -> 16.8.5 - fumadocs-ui: 16.6.7 -> 16.8.5 - fumadocs-mdx: 14.2.8 -> 14.3.2 - fumadocs-openapi: 10.3.13 -> 10.8.1 - migrate deprecated sidebar.tabs to top-level tabs prop - fix pre-existing typo (slots.paremeters) surfaced by stricter openapi types * fix(docs): revert sidebar.tabs migration to keep deploy compat The top-level tabs prop is only on fumadocs-ui 16.7+; deploy env was still resolving an older type and failing typecheck. sidebar.tabs is deprecated but still functional — keep it for now. |
||
|
|
bdc42a2d3f |
fix(md-render): fix markdown rendering in file viewer (#4458)
* fix(md-render): fix markdown rendering in file viewer * fix(md-render): use Children.map in pre handler for robustness * fix(md-render): add not-italic to fallback code element * fix(md-render): fix cloneElement type error and include tables improvements - Fix TypeScript build error: type isValidElement<Record<string, unknown>> so cloneElement accepts data-block prop - Column sidebar: use CSS min() for responsive width instead of fixed 400px - Table: boolean cell toggle only fires when clicking the checkbox element directly (via data-boolean-cell-toggle), not anywhere on the cell - Table: double-clicking a boolean cell no longer opens edit mode - Table: move row-select mousedown to the <td> to widen the hit target - Table: run/stop button prevents row-select on mousedown - Table: SelectAllCheckbox made keyboard-accessible; checkbox is pointer-events-none |
||
|
|
0925e2d27b | fix(agent): drop temperature param for claude-opus-4-7 (#4459) | ||
|
|
8f78635dee |
fix(ui): grey subagent tool calls and soften failure copy (#4457)
* fix(ui): Adjust tool opacity, failed tool wording * fix(ui): scope opacity to subagent groups, lowercase fallback error label |
||
|
|
09f4c94b3c |
feat(block): Allow wait block to wait up to 30 days (#4331)
* 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 * feat(block): Allow wait block to wait up to 30 days * restore ff * Filter out waits from hitl endpoints * Use correct count, filtering out wait blocks * improvement(wait): tighten poll route and pause-manager helpers - Parallelize per-row dispatch with Promise.all - Add status='paused' guard on nextResumeAt rewrite to prevent clobbering concurrent resumes - Extract computeEarliestResumeAt + PauseResumeManager.setNextResumeAt helpers - Use canonical PausePoint type in poll route (drop StoredPausePoint) - Narrow UNIT_TO_MS via as const + WaitUnit guard - Bump LOCK_TTL_SECONDS above route maxDuration - Clearer error when allowedPauseKinds rejects a resume --------- Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> |
||
|
|
1baa58085a |
fix(posthog): align tool params with subBlock canonical to fix missing-field error (#4455)
Tool params were named `personalApiKey` but the subBlock resolves to canonical `apiKey`, so canonical-group resolution wrote the value to params.apiKey while the validator looked up params.personalApiKey and reported it missing. Renames `personalApiKey` -> `apiKey` in get_person, query, list_persons, delete_person, and types.ts. Also tightens check-block-registry.ts so a subBlock with canonicalParamId no longer satisfies a tool param lookup by its raw id (the raw id is deleted during extraction). |
||
|
|
0337ccd7f3 |
feat(credentials): add Atlassian service account credentials (#4432)
* 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 * feat(credentials): add Atlassian service account credentials * improvement(credentials): tighten Atlassian service account plumbing - Collapse fetchOAuthTokenBundle into fetchOAuthToken (returns the bundle) - Reuse serviceAccountJsonSchema in the JSON form instead of hand-rolled checks - Use parseAtlassianErrorMessage for log details; drop one-line bearer helper - Extract ATLASSIAN_SERVICE_ACCOUNT_PROVIDER_ID/_SECRET_TYPE constants - Use Drizzle .returning() instead of post-insert SELECT - Helper for the duplicated 401/403 + non-OK pattern in the validator * docs(credentials): add Atlassian service account setup guide - New /integrations/atlassian-service-account doc covers token creation, scope selection, and adding the credential to Sim - Form's "View setup guide" link now points at the doc - Fix the existing Google form link that pointed to the wrong path Screenshot TODOs left inline as MDX comments for the docs team. * docs(credentials): add Atlassian service account screenshots - Auth type picker, Sim add-credential modal, Jira block credential dropdown - Scope-picker screenshot still TODO * docs(credentials): add Atlassian scope picker screenshot * fix(credentials): address greptile feedback on Atlassian SA - Drop stale 'email and API token' copy from the service description (we only collect a token + domain, no email field) - Move duplicate display-name check inside the create transaction so concurrent POSTs can't both pass the check and insert duplicates * fix(docs): move Atlassian screenshots to docs/public Docs site serves /static/* from apps/docs/public, not apps/sim/public — matches the existing google-service-account screenshot convention. * fix(credentials): address review feedback on Atlassian SA - SSRF: only accept *.atlassian.net / *.jira-dev.com hosts before fetching tenant_info, blocking probes against localhost/internal IPs - Confluence spaces selector: pull cloudId from the SA secret instead of calling accessible-resources, which 401s for scoped service-account tokens - Case-insensitive https?:// strip so HTTPS://team.atlassian.net normalizes correctly * chore: merge staging and bump API validation route baseline to 727 * perf(credentials): single-resolve in confluence spaces selector Atlassian SAs were hitting resolveOAuthAccountId twice (once via refreshAccessTokenIfNeeded, once directly to read cloudId) and decrypting the secret twice (via getAtlassianServiceAccountToken inside refresh, then again via getAtlassianServiceAccountSecret). Resolve once up front and branch the whole flow on the result — SA path skips refresh entirely and pulls token+cloudId from a single secret read. * refactor(credentials): consolidate Atlassian SA creation into /api/credentials Atlassian service-account creation lived in its own route, contract, and mutation hook, copy-pasting ~140 lines of insert/membership/audit/posthog boilerplate from /api/credentials. Two endpoints means two authz paths, two audit shapes, two TOCTOU stories — they will drift. Fold Atlassian into the existing service_account branch of /api/credentials, dispatching by providerId. The Atlassian validator (tenant_info + Bearer /myself, SSRF host allowlist, typed error codes) lives in lib/credentials/atlassian-service-account.ts and is the only Atlassian- specific piece left. AtlassianValidationError maps to a {code, error} 400 in the existing catch block; the rest of the flow (transaction, members, audit, posthog, dup-check) is now shared with Google SA + env credentials. Delete: - /api/auth/atlassian-service-account route - contracts/atlassian-service-account.ts + barrel export - useCreateAtlassianServiceAccount hook - API audit baseline 727 → 726 Both forms (Google JSON-key, Atlassian token+domain) now call useCreateWorkspaceCredential with the appropriate body shape. * fix(credentials): close TOCTOU and restore typed errors after consolidation - Add inner duplicate-guard inside the create transaction (DuplicateCredentialError) to close the race that the outer findExistingCredentialBySource leaves open. service_account rows have no DB-level unique index on (workspaceId, providerId, displayName), so this is the actual safety net. Tx-internal check applies to Google + env_workspace too — race-safety win for all credential types. - Re-emit {code: 'duplicate_display_name', error: ...} on conflict so the form's ERROR_MESSAGES.duplicate_display_name mapping is reachable again. - Thread Atlassian-specific audit metadata (atlassianDomain, atlassianCloudId) back into recordAudit; consolidation had dropped them. - Use ATLASSIAN_SERVICE_ACCOUNT_PROVIDER_ID constant in contract superRefine. - Drop `error: any` in catch in favor of `error: unknown` + getPostgresErrorCode. * chore(credentials): drop dead createWorkspaceCredentialBodySchema + updateWorkspaceCredentialBodySchema Both shadowed the actually-used schemas (createCredentialBodySchema / updateCredentialByIdBodySchema) and were missing the apiToken/domain Atlassian fields. A future change could pick the wrong one and silently drop those fields. Confirmed zero non-definition references in the repo (grep across apps/, packages/, scripts/ minus build artifacts). * fix(credentials): scope inner duplicate re-check to service_account OAuth dedupes by accountId, env_* by envKey — both have DB-level partial unique indexes that surface as 23505. The previous inner re-check fired for all types and always threw DuplicateCredentialError, which mapped to 'duplicate_display_name' in the UI even when the real conflict was a duplicate OAuth account or env key. Restrict the in-tx re-check to service_account (the only type without a DB-level index) and let the 23505 handler emit a generic message for everything else. --------- Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> |
||
|
|
c09e0a04bd |
fix(copilot): disambiguate VFS upload paths to prevent stale-row reads (#4454)
* fix(copilot): disambiguate VFS upload paths to prevent stale-row reads |
||
|
|
a9e9ecf767 |
feat(posthog): correlate task events with copilot logs via request_id (#4453)
* feat(posthog): correlate task events with Go logs via request_id Auto-injects server request_id into all PostHog server events from AsyncLocalStorage context. Adds task_request_started client event fired when SSE traceparent response header arrives, carrying the trace ID used by Go for log correlation. task_generation_aborted now includes the in-flight request_id when available. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * improvement(posthog): tighten trace ID parse and verbose comments * fix(posthog): use traceparent header as canonical request_id source --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
6bc34c5a68 | feat(exa): add date filters to search (#4451) | ||
|
|
af8401928b |
improvement(logs): increase log details panel max width from 40vw to 60vw (#4449)
* improvement(logs): increase log details panel max width from 40vw to 60vw * chore(logs): fix stale 65vw references in JSDoc comments |
||
|
|
ab551ccb41 |
refactor(tables): decouple UI display from DB position (#4448)
* refactor(tables): phase 1 — gutter numbering from array index
Delete the PositionGapRows component, the gap-fill loop, and the
GAP_CHECKBOX_CLASS / GAP_ROW_LIMIT / PositionGapRowsProps surface area.
The server's recompactPositions() guarantees positions are 0..N-1
contiguous in the unfiltered view, so the phantom-row machinery has
been defending against a state that essentially never happens.
DataRow now receives an arrayIndex prop and renders {arrayIndex + 1}
in the gutter. Selection coordinates still flow through row.position;
that switches in phase 2.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* refactor(tables): phase 2-5 — selection by array index, checks by row id
Decouple Tables UI selection coordinates from DB position:
- rowIndex semantics shift from row.position to array index across
selection state, mouse handlers, keyboard nav, paste, scrollIntoView
- checkedRows: Set<number> (position) → Set<string> (rowId), survives
sort/filter and realtime row inserts
- lastCheckboxRowRef stores rowId; shift-click range resolves to current
array indices for visual-order ranges
- Drop positionMap/maxPosition derived state in favor of direct rowsRef
reads
- ExpandedCellPopover anchors via data-row-id (row-id-stable) instead
of data-row (array index)
- collectRowSnapshots accepts Iterable<TableRowType> directly
- Add bounds-validation effect to clamp anchor/focus when rows.length
shrinks (sort change, pagination, realtime delete)
- Drop redundant arrayIndex prop on DataRow (rowIndex now equals it)
Server-side position math stays at API boundary only: insertRow,
duplicateRow, shift-Enter append, paste create-batch, undo snapshots.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* refactor(tables): rowId-stable selection across sort, position math via reduce
- Track anchor/focus by rowId so same-length sort changes remap selection
to the new visual index instead of leaving it on a different row.
- Replace last-row position lookups with Math.max reduce in paste's
create-batch and append-row's undo snapshot — under non-position sorts,
the last visual row's position is not the largest.
- Trim a navigation-noise comment and tighten two over-explanatory ones.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(tables): guard rowId remap effect and document paste batch position
- Skip the validation effect when rows is empty (transient state during
initial load of a new sort/filter before keepPreviousData populates) so
selection survives uncached query changes.
- Skip when isColumnSelection is true; the column-selection pinning effect
owns focus.rowIndex for those, and remapping would shrink a full-column
range to wherever the captured endpoints happened to land after reorder.
- Comment lastRowPosition's hoist invariant so a future refactor doesn't
move it inside the loop and produce colliding positions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
e14a3a5fa9 |
fix(tables): suppress phantom rows on sort, center gutter numbers, stop select-all viewport jump (#4445)
* fix(tables): suppress phantom rows on sort, center gutter numbers, stop select-all viewport jump * fix(tables): suppress scroll on Ctrl+A select-all Cmd/Ctrl+A duplicates the select-all logic but missed the suppressFocusScrollRef flag, so the keyboard path still triggered the viewport jump. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
51addc5767 | fix(terminal): use wall-clock duration for loop iterations with concurrent children (#4443) | ||
|
|
1166d8274e |
feat(logs): add Logs block for querying execution logs from workflows (#4442)
* feat(logs): add Logs block for querying execution logs from workflows * fix(logs): guard transformResponse on non-2xx and correct executionMetadata description - Add response.ok check in all three logs tools' transformResponse so a 4xx/5xx body cannot be silently treated as a success payload (defense in depth; the executor already throws on non-2xx before transform runs). - Drop totalTokens from executionMetadata description in block and tool outputs since the snapshot route does not emit it. |
||
|
|
9eeb1b2cdb |
improvement(mothership): streaming state transitions (#4439)
* improvement(mothership): improve streaming state transitions * address comments |
||
|
|
1dc6f7dd09 |
fix: double wrap reponse of guest session handler (#4438)
* 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 double wrap reponse of guest session handler * remove dead code, and fix test --------- Co-authored-by: Waleed <walif6@gmail.com> Co-authored-by: Theodore Li <theodoreqili@gmail.com> Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com> Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: Theodore Li <theo@sim.ai> |
||
|
|
029ac9fb05 |
fix(logs): split summary/detail contracts to make trace tab gate type-safe (#4431)
* fix(logs): split summary/detail contracts to make trace tab gate type-safe The Trace tab was silently missing from the Log Details sidepanel because list and detail rows shared one WorkflowLog type with executionData: z.unknown(). The UI couldn't distinguish a summary row (no spans) from a detail row (with spans), so the tab gate read undefined and hid itself. Splits into WorkflowLogSummary (list) and WorkflowLogDetail (typed executionData with optional traceSpans). Detail and by-execution routes both write through to the same logKeys.detail(id) cache, eliminating the two-key fragmentation that caused the merge memo workaround. List route moves to cursor pagination on (sortValue, id) with proper NULLS LAST handling and SQL-side sort across workflow + job execution tables. Detail route now requires and asserts workspaceId. Deep-link path uses useLogByExecutionId instead of auto-paginating the entire workspace. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): audit follow-ups — render side-effect, stats invalidation, enhanced spread order - Move onActiveTabChange call from render into useEffect to avoid side-effects during render (StrictMode safety). - Re-add logKeys.stats() invalidation to cancel/retry mutations so the dashboard reflects status flips immediately. - Reorder enhanced: true after ...execData spread in detail and by-execution routes so the literal discriminator is never overwritten by stale execData. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): mirror SQL NULLS LAST in JS merge for cursor consistency The in-memory merge of workflow + job pages negated the comparator for DESC, which placed null sort values at the start. SQL orders both ASC and DESC with NULLS LAST, so DESC pages emitted a cursor {v: <last non-null>, id: ...} while null rows still satisfied the cursor predicate (OR sort_expr IS NULL) on the next page — producing duplicate null rows across pages on cost/duration sorts. Handle nulls explicitly in the JS comparator so they always sort last regardless of direction, matching the SQL ordering. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): final-audit follow-ups — stable tab callback, byExecution invalidation, optimistic detail patch, trace loading state - Wrap LogDetails -> LogDetailsContent onActiveTabChange in useCallback so the child useEffect doesn't refire on every parent render. - Add logKeys.byExecutionAll() to cancel + retry invalidation so the table-embedded sidebar picks up status changes immediately. - Optimistic write-through to logKeys.detail in useCancelExecution so the open sidebar reflects 'cancelling' instantly; rolls back on error. - Distinguish trace loading from trace-empty: when log.executionData is not yet fetched, render "Loading trace…" instead of the empty state. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(logs): migrate stores/components to contract types Replace the legacy `WorkflowLog` / `LogsResponse` / `WorkflowData` / `CostMetadata` / `ToolCallMetadata` shapes in `stores/logs/filters/types.ts` with direct use of the contract types `WorkflowLogSummary`, `WorkflowLogDetail`, and a new `WorkflowLogRow` alias for surfaces that render either form. Removes the `summaryToWorkflowLog` / `detailToWorkflowLog` bridge in the React Query layer along with their double-cast annotations. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(logs): address PR review feedback - Whitelist sort columns against logSortBy enum to prevent client crash when non-sortable headers (workflow, trigger) reach the contract parser. - Extract fetchLogDetail helper shared by /api/logs/[id] and /api/logs/by-execution/[executionId] — collapses ~360 duplicated lines to a single source of truth keyed on lookup column. * fix(logs): exclude job logs when level filter is workflow-only When level=running or level=pending (workflow-only states involving endedAt/pausedExecutions semantics), jobLevelConditions stayed empty so no level constraint reached jobConditions — every job log in the workspace leaked into the result. Skip the job side entirely when the level filter has no job-applicable values (error/info). * chore(logs): drop dead utils — mapToExecutionLog and friends Remove ExecutionLog/RawLogResponse/ExecutionCost/LogWithExecutionData/ TraceSpan/BlockExecution interfaces and the mapToExecutionLog, mapToExecutionLogAlt, extractOutput functions — all unreferenced after the contract split. -212 lines. * chore(logs): drop unused LOG_COLUMN_ORDER and LogColumnKey * fix(logs): hydrate filters from URL synchronously on mount The previous useEffect-based initializeFromURL caused useLogsList and useDashboardStats to fire once with default store filters, then refetch after the effect updated filters from the URL. Move the initial hydrate into a useState lazy initializer so the first render already reads URL-derived filters; the popstate handler keeps the existing effect for back/forward navigation. * chore(logs): trim verbose comments added during PR Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): guard navigation arrows when selected log is off-page Deep-linked logs resolved via useLogByExecutionId may not be in the current page list, leaving selectedLogIndex at -1. The hasNext prop was evaluating -1 < logs.length - 1 (true for any non-empty list), which enabled the next arrow and jumped to the first item on click. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(logs): sync active-tab callback before paint to keep keyboard guards aligned Run the resolvedTab → onActiveTabChange propagation in useLayoutEffect so the parent's activeTabRef updates synchronously before the next paint. This closes the brief window where window keydown handlers in the logs page would still see activeTabRef.current === 'trace' and short-circuit arrow-key navigation immediately after switching to a log without a Trace tab. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |