Navigation Menu
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Comparing changes
Open a pull request
base repository: simstudioai/sim
base: v0.7.12
head repository: simstudioai/sim
compare: v0.7.13
- 18 commits
- 185 files changed
- 4 contributors
Commits on Jun 22, 2026
-
refactor(frontend-arch): migrate server state to React Query, collaps…
…e duplicate workflow-state cache, granular error boundaries (#5168) * refactor(session): migrate SessionProvider to React Query useSessionQuery Replace the hand-rolled useState/useEffect/loadSession session loading in SessionProvider with a useSessionQuery() React Query hook. The SessionContext shape is unchanged ({ data, isPending, error, refetch }) so no consumer changes. The 'upgraded' path still forces a fresh DB read via client.getSession({ query: { disableCookieCache: true } }) (refetch() cannot pass disableCookieCache) and writes the result via queryClient.setQueryData, then invalidates ['organizations']/['subscription'] as before. * refactor(workflows): collapse duplicate workflow-state cache The registry store fetched the GET /api/workflows/[id] envelope inline via requestJson while useWorkflowState cached the same endpoint's mapped state under workflowKeys.state(id) — two requests, two cache shapes, never reconciled. Collapse to one request + one cache entry keyed by workflowKeys.state(id): - Add hooks/queries/utils/fetch-workflow-envelope.ts: a standalone fetchWorkflowEnvelope(id, signal) returning the full GetWorkflowResponseData. Standalone (not in workflows.ts) to avoid a store -> query-hook import cycle. - useWorkflowState/useWorkflowStates now query the envelope and derive the mapped WorkflowState via select (mapWorkflowState), so consumers see the identical mapped shape from the shared entry. - The store's loadWorkflowState reads via getQueryClient().fetchQuery({ staleTime: 0 }) instead of raw requestJson — always-fresh (preserving the prior always-fetch boot/refresh semantics, incl. the socket handle-resource-event refresh path that has no separate state invalidation), in-flight deduped, writing into the same cache entry the hooks read. Request-id staleness guard, deployment-cache priming, cross-store projection, and the active-workflow-changed event are all preserved unchanged. * fix(workspace): add granular error boundaries to logs, knowledge, and files panels Scope a crash in one workspace panel to that panel instead of the whole workspace shell. Each boundary reuses the shared ErrorState component and mirrors the existing tables/settings error.tsx convention. * refactor(unsubscribe): migrate page to React Query Replace the hand-rolled useState+useEffect+requestJson server-state in the unsubscribe page with React Query hooks. Add useUnsubscribe (validation/load query, keyed by email+token, auto-runs on mount via enabled) and useUnsubscribeMutation (unsubscribe action, reconciles cached preferences on success) in hooks/queries/unsubscribe.ts with a hierarchical key factory. Export UnsubscribeData/UnsubscribeActionResponse/UnsubscribeType type aliases from the existing user contract; loading/error/success now derive from the query and mutation objects with no local server-state mirror. * test(frontend-arch): cover session race fix, workflow-state cache collapse, unsubscribe, error boundary Add targeted tests for the four frontend-architecture refactors: - session-provider: upgrade-path ordering — fresh disableCookieCache read wins over a late-resolving stale mount query (proves the cancelQueries guard) - fetch-workflow-envelope + registry store: single shared state(id) cache entry, always-refetch (staleTime 0), request-id staleness guard - unsubscribe: query enable-gating + mutation cache reconcile - logs error boundary: renders ErrorState + reset wiring (also first ErrorState coverage) * fix(session): harden upgrade path + address review feedback - Reconcile plan surfaces after upgrade even when the fresh disableCookieCache read fails: invalidate ['organizations']/['subscription'] regardless of the bypass-read outcome (they read server truth, not the cookie cache). The valid cookie-cached session is still served, so a transient failure no longer signs the user out or leaves the just-upgraded plan looking stale. Org-activate fallback stays gated on having a session. - Use a bare return in the cancelled branch of refreshAfterUpgrade (the caller discards the value) for clearer intent; caller coerces with ?? null. - Make the upgrade tests deterministic: the mount mock honors the abort signal like the real fetch-backed client, and assertions read the query cache (the state cancelQueries/setQueryData/invalidation actually govern) instead of the async-rendered context value. * refactor(session): break provider<->hook type cycle, fail-fast session query Address review feedback: - Move the AppSession type to lib/auth/session-response.ts (the module that produces it) so useSessionQuery and SessionProvider both import it from there, eliminating the provider <-> query-hook import cycle. - Add retry: false to useSessionQuery, restoring the prior fail-fast contract (the global QueryClient default is retry: 1; an auth failure should surface immediately rather than retry a request that won't succeed). - Return null (not the fetched value) from refreshAfterUpgrade's cancelled branch to make the cancellation contract explicit.
Configuration menu - View commit details
-
Copy full SHA for e96b150 - Browse repository at this point
Copy the full SHA e96b150View commit details -
feat(providers): add Sakana AI provider with Fugu models (#5169)
* feat(providers): add Sakana AI provider with Fugu models OpenAI-compatible provider at https://api.sakana.ai/v1 (bearer auth). Registers fugu (fast default) and fugu-ultra (reasoning flagship), both 1M context. BYOK-only, never hosted/auto-billed. Streaming, tool loop, and response_format supported; attachments mirror deepseek (unsupported in the current adapter). * fix(providers): defer Sakana structured output until after tool loop OpenAI-compatible backends reject a request carrying both response_format and active tools/tool_choice. Mirror the LiteLLM pattern: withhold the JSON schema while tools are active and apply it on a final tool-free call (tool_choice: none) for both streaming and non-streaming paths. * fix(providers): harden Sakana tool-loop error + final-stream tool_choice - Rethrow tool-loop failures instead of swallowing them, so a failed run surfaces as a ProviderError rather than a partial success (matches LiteLLM). - Force tool_choice: 'none' on the post-tool streaming pass so the model cannot emit fresh tool calls that the text-only stream adapter would drop. * fix(providers): Sakana streaming usage + filtered-tools stream guard - Pass stream_options: { include_usage: true } on both streaming calls so token/cost data is captured (the shared OpenAI-compatible stream helper only fills usage from chunk usage, which the API omits without the flag). - Include !hasActiveTools in the early-stream guard so requests whose tools are all filtered out (e.g. usageControl 'none') still take the fast streaming path instead of the tool-loop path. Mirrors LiteLLM. * fix(providers): answer every Sakana tool_call to keep message history valid An assistant message lists all tool_calls, so a call for an unconfigured tool must still get a matching `tool` response or the next request violates the OpenAI message contract. Emit an error tool-result for unknown tools instead of dropping them. * test(session): de-flake SessionProvider normal-load test flush() only drained microtasks, so the query->render update occasionally lost the race and ctx.data was still null after the flush budget. Yield one macrotask tick per flush so React Query's notifyManager and deferred renders settle deterministically. Verified across repeated local runs.
Configuration menu - View commit details
-
Copy full SHA for 844733a - Browse repository at this point
Copy the full SHA 844733aView commit details -
feat(trigger): add trigger-eu-region flag to switch runs to eu-centra…
…l-1 (#5173) * feat(trigger): add trigger-eu-region flag to switch runs to eu-central-1 Global on/off feature flag routing every Trigger.dev run from the default us-east-1 to eu-central-1 via the per-trigger region option, resolved at each dispatch site through resolveTriggerRegion. * test(trigger): mock resolveTriggerRegion in delete-async route test The route now pulls in feature-flags (which imports isAppConfigEnabled from env-flags); the test's partial env-flags mock made that access throw. Stub the region module and assert the region option on the dispatch.
Configuration menu - View commit details
-
Copy full SHA for 707c3cc - Browse repository at this point
Copy the full SHA 707c3ccView commit details
Commits on Jun 23, 2026
-
feat(pi): add pi coding agent harness (#5178)
* feat(pi): add pi coding agent harness * formatting * update docs * change version num * guard to prevent prs on error * update param visibility * address security concerns * fix tests * reorder:
Configuration menu - View commit details
-
Copy full SHA for 6333919 - Browse repository at this point
Copy the full SHA 6333919View commit details -
Configuration menu - View commit details
-
Copy full SHA for ccc6954 - Browse repository at this point
Copy the full SHA ccc6954View commit details -
feat(pii): build & own combined PII (analyzer + anonymizer) image (#5176
) * feat(presidio): build & own combined analyzer+anonymizer image Replace the stock mcr.microsoft.com/presidio-* sidecar images with a single image we build and push to ECR/GHCR. A thin FastAPI service constructs one AnalyzerEngine + one AnonymizerEngine at startup and serves both on port 3000 (/health, /supportedentities, /analyze, /anonymize) so the app needs one PRESIDIO_URL. English only; pinned presidio 2.2.362 + en_core_web_lg 3.8.0. Bakes in the native check-digit VIN recognizer and registers 12 English recognizers Presidio ships but does not load by default (UK_NINO, AU_*, IN_*, SG_*), taking the supported English set from 19 to 32. * feat(presidio): add multi-language support (es/it/pl/fi) Configure a multi-language spaCy NLP engine (en/es/it/pl/fi lg models) and explicitly register the national-id recognizers Presidio ships but does not load by default: ES_NIF/NIE, IT_FISCAL_CODE/DRIVER_LICENSE/VAT_CODE/PASSPORT/ IDENTITY_CARD, PL_PESEL, FI_PERSONAL_IDENTITY_CODE. Verified the NLP-engine + explicit-registration path detects in-language (Finnish id, score 1.0). * improvement(presidio): address review feedback - Register VIN under all served languages, not just en (Bugbot: VIN missed for non-English language routing). - Bump HEALTHCHECK start-period to 180s — five lg models load at import (Bugbot). - Drop --no-cache-dir so the pip cache mount actually works (Greptile). - Pydantic request models for /analyze + /anonymize so missing 'text' returns 422 not 500; default operator 'type' to 'replace' instead of KeyError->500 (Greptile). * refactor(pii): rename presidio image artifacts to pii Rename the image/repo/secret/files from 'presidio' to 'pii' for clarity — the service does PII detection + anonymization (and backs the guardrails block's block/mask), not just redaction, and 'pii' matches existing pii-* naming. docker/presidio.Dockerfile -> docker/pii.Dockerfile docker/presidio/ -> docker/pii/ ghcr.io/simstudioai/presidio -> .../pii ECR_PRESIDIO secret -> ECR_PII (infra side already renamed) No behavior change — paths/identifiers only. * refactor(pii): move service to apps/pii, make image ECR-only - Move server.py + requirements.txt from docker/pii/ to apps/pii/ (source belongs under apps/, matching app/realtime; Dockerfile stays in docker/). Add a minimal @sim/pii package.json so the apps/* bun workspace glob accepts the Python service. - Repoint docker/pii.Dockerfile COPY paths to apps/pii/; rename the container user presidio -> pii. - Drop GHCR for pii — it's a private ECS sidecar pulled from ECR, never published. Removed it from the arm64/manifest (GHCR-only) jobs and guarded the build-amd64 tag step to skip GHCR when no ghcr_image is set.
Configuration menu - View commit details
-
Copy full SHA for 0191a61 - Browse repository at this point
Copy the full SHA 0191a61View commit details -
fix(pii): listen on 5001 to avoid app :3000 collision (awsvpc) (#5182)
* fix(pii): bind a configurable $PORT to avoid app :3000 collision The pii image hardcoded uvicorn --port 3000 and ignored env. In the app ECS task (awsvpc) all containers share one network namespace, and the app owns 3000 — so the sidecar must listen elsewhere (the stock presidio images honored PORT and ran on 5002/5001). Bind ${PORT} (shell-form CMD), default 5001, and update EXPOSE/HEALTHCHECK accordingly so the taskdef can set PORT=5001. Verified: default binds 5001; PORT=5002 override binds 5002; /analyze works on the overridden port. * fix(pii): hardcode port 5001 (drop $PORT indirection) EXPOSE can't be parameterized, so the configurable-PORT approach left EXPOSE showing 5001 regardless (Greptile P2). We own both the image and the taskdef and only ever need 5001, so hardcode it: exec-form CMD on 5001, EXPOSE 5001, healthcheck on 5001. Runtime cmdline is identical to the verified ${PORT} default (uvicorn ... --port 5001).Configuration menu - View commit details
-
Copy full SHA for 4d2e7d5 - Browse repository at this point
Copy the full SHA 4d2e7d5View commit details -
feat(guardrails): PII redaction via Presidio sidecar (native VIN, per…
…-rule language) (#5174) * fix(logs): run PII redaction over HTTP and fix Presidio provisioning - resolve the guardrails venv via candidate paths and fail fast instead of silently falling back to system python3 (the misleading "Presidio not installed" that broke redaction and the guardrails block in deployed runtimes) - install the en_core_web_lg spaCy model in setup.sh and app.Dockerfile - route log redaction through an internal /api/guardrails/mask-batch endpoint so Presidio always runs in the app container, including async executions that persist inside the trigger.dev runtime * fix(guardrails): chunk + time-bound internal PII mask requests - chunk maskPIIBatchViaHttp by count (2000) and bytes (256KB) so large executions split across requests and never hit the contract's 100k cap - add AbortSignal.timeout(45s) per request so a slow/unreachable app container aborts and the caller scrubs, instead of hanging the trigger.dev job - catch maskPIIBatch failures in the route: log and return a structured 500 (broken venv fails loudly server-side; caller still scrubs, no leak) - add mask-client tests (order across chunks, count split, non-2xx, empty) * fix(guardrails): mint internal token per mask request A single token (5min TTL) could expire mid-batch when a large execution fans out into many sequential chunk requests; mint one per request instead. * feat(guardrails): run PII via Presidio sidecars + TS recognizer registry - replace the per-call python3 subprocess (cold spaCy load every call) with two long-lived Presidio sidecars (analyzer + anonymizer) reached over HTTP; the app image no longer carries Python/Presidio/venv - add PRESIDIO_ANALYZER_URL / PRESIDIO_ANONYMIZER_URL - move VIN out of Python into a TS recognizer (check-digit validated) behind a CUSTOM_RECOGNIZERS registry so new custom detectors are one entry; masking is handled uniformly by the anonymizer - drive the guardrails block's PII type picker from the shared pii-entities catalog (adds VIN, fixes drift) so block + Data Retention never diverge - delete validate_pii.py, requirements.txt, setup.sh and the Dockerfile venv step * fix(guardrails): bound-parallelize mask batch; refresh stale comments - maskPIIBatch runs per-string sidecar calls with bounded concurrency (8) via mapWithConcurrency, so a chunk of many small leaves finishes within the 45s request timeout instead of aborting and scrubbing; order + fail-on-error kept - drop stale comments referencing the deleted Python venv / 30s subprocess timeout * refactor(guardrails): single Presidio image, native VIN, per-rule redaction language - collapse the analyzer/anonymizer URLs into one PRESIDIO_URL (combined image serves /analyze + /anonymize) - remove the TS VIN recognizer (vin.ts, recognizers.ts) — VIN is now native + multi-language in the image; validate_pii is a thin analyze→anonymize client - trim KR_RRN/TH_TNIN from the catalog (no Korean/Thai model in the image) - add per-rule redaction language: PII_LANGUAGES catalog drives the contract enum, the Data Retention rule modal, and the guardrails block dropdown; resolver + logger thread it through to maskPIIBatch (default en), so non-English entity rules (e.g. ES_NIF) actually fire instead of silently no-op'ing under en * fix(guardrails): correct sidecar port (5001) + README for combined image The combined Presidio image (docker/pii.Dockerfile) serves /analyze + /anonymize on a single port 5001 with native VIN + multi-language recognizers. Fix the PRESIDIO_URL default (was 5002) and rewrite the README, which still described two stock containers and a TS VIN recognizer. * fix(guardrails): coerce stored redaction language in the resolver The persist-path resolver accepted any stored language string, so a stale/invalid code (e.g. a dropped locale) would reach Presidio and scrub the log even though the admin UI shows English. Coerce against the supported set via a shared coercePiiLanguage helper (now reused by the data-retention route too), falling back to en for unknown values. * fix(guardrails): rename PRESIDIO_URL env var to PII_URL Match the infra taskdef, which sets PII_URL on the app container for the combined Presidio sidecar.
Configuration menu - View commit details
-
Copy full SHA for 8f312d2 - Browse repository at this point
Copy the full SHA 8f312d2View commit details -
feat(billing): unify upgrade routing with reason context + storage/ta…
…bles limit emails (#5171) * feat(billing): unify upgrade routing with reason context + storage/tables limit emails * fix(billing): re-arm limit-notification dedup on usage drops (prior-usage + decrement) * fix(billing): isolate per-admin email failures in org limit notifications * fix(billing): re-arm limit dedup at zero usage and zero prior usage (full clear / wipe-rebuild) * fix(billing): make storage-decrement notification re-arm only (never send on a shrink) * fix(billing): resolve recipients before claiming so opt-outs don't burn the dedup threshold * fix(billing): fire table limit emails on upsert inserts via shared notifyTableRowUsage * chore(billing): only log a limit email as sent when a recipient actually received it * chore(billing): match to_jsonb int cast between claim and re-arm for consistency * fix(billing): notify table limits post-commit so a rolled-back insert never emails or burns the claim * feat(pi): swap Pi Coding Agent icon to the pi glyph and use a black bgColor * fix(billing): drop priorUsage re-arm to make dedup a single atomic claim (no duplicate-email race) * docs(billing): move limit-notification rationale to TSDoc, correct tables warn-once behavior * docs(db): note limit_notifications dedup is per-account, not per-table * perf(billing): cut redundant subscription fetches and edge-gate notify to slash DB load * docs(billing): drop self-explanatory inline comments from the notification path
Configuration menu - View commit details
-
Copy full SHA for 77976bc - Browse repository at this point
Copy the full SHA 77976bcView commit details -
fix(trigger): mark cpu-features external to fix deploy build (#5185)
ssh2 became reachable from the trigger background bundle via the Pi local SSH backend (#5178). esbuild then tried to bundle ssh2's optional native dep cpu-features and failed on the missing .node binary. ssh2 requires cpu-features inside a try/catch, so externalizing it is safe.
Configuration menu - View commit details
-
Copy full SHA for 406ae92 - Browse repository at this point
Copy the full SHA 406ae92View commit details -
Configuration menu - View commit details
-
Copy full SHA for bf5077b - Browse repository at this point
Copy the full SHA bf5077bView commit details -
fix(enrichment): stop PDL billing on no-match via required-field gati…
…ng (#5184) PDL bills per matched profile, but each cascade only counts a hit when mapOutput yields a specific field. A confident profile (likelihood >= 6) lacking that field was billed yet recorded as no_match. Pass PDL's required param so it 404s (free) when the extracted field is absent, aligning PDL's billing unit with the cascade's success unit.
Configuration menu - View commit details
-
Copy full SHA for c20d5fc - Browse repository at this point
Copy the full SHA c20d5fcView commit details -
feat(data-retention): workspace-level overrides for retention and PII (…
…#5186) * feat(data-retention): workspace-level overrides for retention and PII * fix(data-retention): hide unmanageable PII rows when flag off, scope override workspace IDs to org, dedupe key type * improvement(data-retention): unify org default and workspace overrides into one policy list * fix(data-retention): clean up overrides for workspaces deselected during edit
Configuration menu - View commit details
-
Copy full SHA for 43fa5ea - Browse repository at this point
Copy the full SHA 43fa5eaView commit details
Commits on Jun 24, 2026
-
improvement(access-controls): ui/ux improvements (#5190)
* improvement(access-controls): ui/ux improvements * remove unused col
Configuration menu - View commit details
-
Copy full SHA for 8b5d746 - Browse repository at this point
Copy the full SHA 8b5d746View commit details -
feat(pii): publish PII image to GHCR and add Presidio sidecar to Helm…
… chart (#5188) * feat(pii): publish PII image to GHCR and add Presidio sidecar to Helm chart * fix(pii): allow app→PII NetworkPolicy egress, global tolerations, topology spread
Configuration menu - View commit details
-
Copy full SHA for 7686706 - Browse repository at this point
Copy the full SHA 7686706View commit details -
feat(file): add Manage Sharing operation to the File block (#5177)
* feat(file): add Set File Sharing operation to the File block Adds a new file_set_sharing operation to the File block (file_v5) that idempotently enables/disables a file's public share link and sets its access mode (public, password, email, SSO). The set_sharing route case reuses upsertFileShare, requires write/admin, gates enabling through the EE public-sharing policy, and records a share audit. Returns an empty url when set to private so a disabled link isn't handed back as a dead link. * fix(file): harden set_sharing — explicit isActive, agent-controllable params, policy gate + perm-check ordering Addresses review findings: - Make isActive explicit/required so a bare call no longer silently enables a public link - Expose isActive/authType/allowedEmails as user-or-llm so agents can disable/configure shares (password stays user-only) - Resolve authType from the existing share before the EE policy gate to close a re-enable bypass - Run the write/admin permission check before the file lookup to remove a file-existence side channel * refactor(file): rename file operation to Manage Sharing Renames the file_set_sharing operation to file_manage_sharing (route literal manage_sharing, tool Manage Sharing) across the contract, route, tool, block, registry, and tests. * fix(file): complete Manage Sharing rename in tools barrel Prior commit's lint-staged dropped the barrel re-export update, leaving index.ts importing the deleted set-sharing module and breaking the block registry check. Point the barrel at manage-sharing. * fix(file): require isActive in tool params type, reject multiple files in manage sharing - FileManageSharingParams.isActive is now required, matching the tool param and contract (no compile-time gap that 400s at runtime) - manage_sharing rejects multiple canonical file IDs instead of silently sharing only the first, matching decompress * fix(file): resolve basic-picker files for manage sharing The basic file-upload picker stores a workspace file as { name, path, key, size, type } with no canonical id, so manage_sharing failed those picks with 'Could not determine the file to share'. The block now passes the picked object as fileInput when it lacks an id, and the route resolves the canonical id from the storage key via getFileMetadataByKey. Contract accepts fileId OR fileInput (mirroring read/get content).Configuration menu - View commit details
-
Copy full SHA for 4554df9 - Browse repository at this point
Copy the full SHA 4554df9View commit details -
feat(file): include public share status in File read output (#5191)
* feat(file): include public share status in File read output The read operation now attaches each workspace file's public share status as a "share" field (the share record, or null when not shared), batch-fetched via getSharesForResources to avoid N+1. Picker/upload input files have no canonical id and carry share: null. * refactor(file): read share status uses visibility vocabulary, no row internals Read's per-file "share" is now { visibility, url, allowedEmails } using the same visibility vocabulary as Manage Sharing: 'private' when not shared (url null, no config) instead of null, otherwise public/password/email/sso with the link. Drops row internals (id, token, resourceType, resourceId, isActive, hasPassword). * fix(file): mark picker files private without a share lookup Input (picker/upload) files only have a synthetic id (storage key/URL), so looking them up in the shares map could collide with a canonical file id and attach the wrong share. Give them an explicit private share instead. * docs(file): terser share-status output descriptions * chore(file): drop verbose comment in read share enrichmentConfiguration menu - View commit details
-
Copy full SHA for 8c5da02 - Browse repository at this point
Copy the full SHA 8c5da02View commit details -
v0.7.13: pii redaction, react query frontend refactor, pi coding agen…
…t harness, sakana fugu provider v0.7.13: pii redaction, react query frontend refactor, pi coding agent harness, sakana fugu provider
Configuration menu - View commit details
-
Copy full SHA for ad0b867 - Browse repository at this point
Copy the full SHA ad0b867View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v0.7.12...v0.7.13
